1. 程式人生 > 實用技巧 >Java-17 集合、正則、map簡單介紹

Java-17 集合、正則、map簡單介紹

1.SimpleDateFormat

  • SimpleDateFormat主要用於將日期進行格式化,可以將Date轉成指定格式的字串,也可以將字串轉成日期。

  • 構造方法:

    public SimpleDateFormat()   預設格式做轉換
    public SimpleDateFormat(String pattern) 按指定格式做轉換
    
  • 成員方法:

    public String format(Date date);
    public Date parse(Strig dateStr) throws ParseExcepiton;
    
  • format方法 date->string

    import java.text.SimpleDateFormat;
    import java.util.Date;
    
    public class SimpleDateFormatDemo1 {
    	public static void main(String[] args) {
    		// 獲取當前時間
    		Date date = new Date();
    		System.out.println(date);
    		// 無參構造方法。預設格式 xxxx/xx/xx 上午 xx:xx
    		SimpleDateFormat sdf = new SimpleDateFormat();
    		String str = sdf.format(date);
    		System.out.println(str);// 2020/10/17 上午10:32
    		
    		SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    		String str2 = sdf2.format(date);
    		System.out.println(str2);// 2020-10-17 10:35:46
    	}
    }
    
    
  • parse方法 string-->date

    public class SimpleDateFormatDemo1 {
    	// throws ParseException丟擲異常
    	public static void main(String[] args) throws ParseException {
            // 宣告Str date格式
            SimpleDateFormat sdf3 = new SimpleDateFormat("yyyy-MM-dd HH/mm/ss");
    		String str3 = "2010-02-02 12/12/12";
            // Str  轉  date
    		Date date2 = sdf3.parse(str3);
    		System.out.println(date2);
    	}
    }
    
    

    注意:一定要保證String的格式 和 SimpleDateFormat中的Patten 保持一致。

  • 日期轉換練習

    // 把字串"2018-10-15 11:11:11" 轉成字串 "11:11:11 15/10/2018"
    import java.text.ParseException;
    import java.text.SimpleDateFormat;
    import java.util.Date;
    public class SimpleDateFormatDemo2 {
    	public static void main(String[] args) throws ParseException {
    		String str1 = "2018-10-15 11:11:11";
    		SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:SS");
    		// 轉換成date
    		Date date = sdf1.parse(str1);
    		System.out.println(date);// Mon Oct 15 11:11:00 CST 2018
    		SimpleDateFormat sdf2 = new SimpleDateFormat("SS:mm:HH dd/MM/yyyy");
    		String str2 = sdf2.format(date);
            // 轉化成String
    		System.out.println(str2);// 11:11:11 15/10/2018
    	}
    }
    
    

2.正則表示式

  • 正則表示式是對字串操作的一種邏輯公式,就是用事先定義好的一些特定字元,及這些特定字元的組合,組成一個"規則字串"。這個“規則字串”的一種過濾。

  • 練習

    // 驗證qq號,不能以0開頭 ,5-15位
    public class RegexDemo1 {
    	public static void main(String[] args) {
    		Scanner  sc = new Scanner(System.in);
    		System.out.println("請輸入QQ號:");
    		String qq = sc.next();
    		boolean result = checkQQ(qq);
    		if (result) {
    			System.out.println("合法QQ");
    		} else {
    			System.out.println("不合格QQ");
    		}
    	}
    	
    	private static boolean checkQQ(String qq) {
    		String regex = "[1-9][0-9]{4,14}";
    		return qq.matches(regex);
    	}
    }
    
  • 常用規則:

    .	任何字元
    \d	數字[0-9]
    \D	非數字 [^0-9]
    \s	空白字元 \r\n\x0B\f\r
    \S	非空白字元
    \w	單詞字元 [a-zA-Z_0-9]
    \W  非單詞字元
    X?	X的0次或1次
    X*	X的0次或多次
    x+  X的一次或多次
    X{n}	X的n次
    X{n,}	X的至少n次
    X{n,m}	至少n次,不超過m次
    [abc]a、b 或 c (簡單類)
    \b	單詞邊界
    
  • 匹配一個整數或小數

    System.out.println("12.34".matches("\\d+(\\.\\d+)?"));
    
  • 匹配手機號

    String phoneRegex = "^((13[0-9])|(14[5|7])|(15([0-3]|[5-9]))|(17[013678])|(18[0,5-9]))\\d{8}$";
    System.out.println("13500000000".matches(phoneRegex));
    
  • 驗證郵箱

    String emailRegex = "^([a-z0-9A-Z]+[-|_|\\.]?)+[a-z0-9A-Z]@([a-z0-9A-Z]+(-[a-z0-9A-Z]+)?\\.)+[a-zA-Z]{2,}$";
    System.out.println("[email protected]".matches(emailRegex));
    
  • split分割

    
    public class RegxDemo2 {
    	public static void main(String[] args) {
    		String str1 = "11,22,33";
    		String[] split1 = str1.split(",");
    		System.out.println(split1[1]);
    		
    		String str2 = "11.22.33";
    		String[] split2 = str2.split("\\.");
    		System.out.println(split2[1]);
    		
    		String path = "C:\\demo\\a.txt";
    		String[] split3 = path.split("\\\\");
    		System.out.println(split3[2]);
    	}
    }
    
    
  • 練習:有一個字串 "2 3 1 11 4" 轉成"1 2 3 4 11"

    public class RegexDemo3 {
    	public static void main(String[] args) {
    		String str = "2 3 1 11 4";
    		String[] arr = str.split(" ");
    		// 建立等長int陣列
    		int[] arr2 = new int[arr.length];
    		for (int i=0;i<arr.length;i++) {
    			String s = arr[i];
    			int a = Integer.parseInt(s);
    			arr2[i] = a;// 把轉成int值儲存int陣列
    		}
    		// 對int陣列排序
    		Arrays.sort(arr2);
    		// 遍歷拼接
    		StringBuilder builder = new StringBuilder();
    		for (int i=0;i<arr2.length;i++) {
    			builder.append(arr2[i]).append(" ");
    		}
    		System.out.println(builder.toString().trim());
    	}
    }
    
  • 練習:

    // 1+2+3+4...+10=55
    public class LianxiaddDemo {
    	public static void main(String[] args) {
    		StringBuilder s = new StringBuilder();
    		int sum = 0;
            // for迴圈不能使用  加號 拼接字串否則效能很低。
    		for (int i=1;i<=10;i++) {
    			s.append(i).append("+");
    			sum += i;
    		}
    		String s2 = s.substring(0, s.length()-1);
    		System.out.println(s2 + "=" + sum);
    	}
    }
    
  • 正則替換

    replaceAll();

  • 把手機號中間四位替換*

    public class RegexDemo4 {
    	public static void main(String[] args) {
    		String mobile = "13333333333";
    		String result = mobile.replaceAll("(\\d{3})(\\d{4})(\\d{4})", "$1****$3");
    		System.out.println(result);
    	}
    }
    
  • 獲取三個字母單詞

    import java.util.regex.Pattern;
    import java.util.regex.Matcher;
    
    public class RegexDemo5 {
    	public static void main(String[] args) {
    		String str = "ni hao a wo jiao xiao liu ? ni shi shui?";
    		// 獲取Pattern物件
    		Pattern p = Pattern.compile("\\b[a-zA-Z]{3}\\b");
    		// 獲取Matcher, Matcher 中封裝了所有匹配結果
    		Matcher m = p.matcher(str);
    		// 獲取結果
    		while (m.find()) {
    			System.out.println(m.group());
    			// hao
    			// liu
    			// shi
    		}
    	}
    }
    
    

    注意:m.group不能單獨使用,需要先m.find才能使用m.group

3.集合

  • 面嚮物件語言對事務的體現都是以物件形式,所以為了方便對多個物件的操作,Java提供了集合類。

  • 陣列和集合類同是容器,它們不同?

    1.陣列雖然也可以儲存物件,但長度是固定的,集合長度是可變的。
    2.陣列中可以儲存基本資料型別,集合只能儲存物件。
    
  • 集合缺點:

    集合只能用於儲存物件,集合長度是可變的,集合可以儲存不同型別物件。
    
  • 集合類關係圖:

    虛線表示介面,實線表示類

  • Collection中方法

    • add 新增

      Collection c = new ArrayList();
      c.add(123);// 123是Integer型別
      c.add(12.4);
      c.add("helloworld");
      System.out.println(c);// [123, 12.4, helloworld]
      
    • remove 移除

      boolean r = c.remove(123);
      System.out.println(r );// true
      
    • clear清空

      
      
    • isEmpty是否為空

      System.out.println(c.isEmpty());
      
    • size集合長度

      System.out.println(c.size());
      
    • contains包含

      System.out.println(c.contains(12.4));
      
    • addAll 新增所有

      import java.util.ArrayList;
      import java.util.Collection;
      import java.util.LinkedList;
      
      public class CollectionDemo2 {
      	public static void main(String[] args) {
      		Collection c1 = new ArrayList();
      		c1.add("c1-1");
      		c1.add("c1-2");
      		c1.add("c1-3");
      		Collection c2 = new LinkedList();
      		c2.add("c2-1");
      		c2.add("c2-2");
      		c2.add("c2-3");
      		// c2 元素 新增 c1中
      		c1.addAll(c2);
      		System.out.println(c1);
      	}
      }
      
    • removeAll 移除所有

      c1.removeAll(c2);
      
    • containsAll 是否全部包含

      c1.containsAll(c2);
      
    • retainAll 取交集

      c1.retainAll(c2)
      
  • Collection 遍歷

    • 一種集合轉陣列,另一種通過迭代器遍歷。
    import java.util.ArrayList;
    import java.util.Collection;
    import java.util.Iterator;
    
    public class CollectionDemo3 {
    	public static void main(String[] args) {
    		Collection  c = new ArrayList();
    		c.add("1");
    		c.add("1");
    		c.add("2");
    		c.add("3");
    		c.add("4");
    		System.out.println(c);
    		// 1.集合轉資料
    		Object[] array = c.toArray();
    		// 遍歷
    		for (int i=0;i<array.length;i++) {
    			System.out.println(array[i]);
    		}
    		// 2.迭代器
    		Iterator it = c.iterator();
    		// 判斷是否有下一個值
    		while (it.hasNext()) {
    			// 列印下一個值
    		System.out.println(it.next());
    		}	
    	}
    }
    
    
  • List中方法

    • 有序的,元素可以重複

    • add(int index,E element) 插入

    import java.util.ArrayList;
    import java.util.Collection;
    import java.util.List;
    
    public class ListDemo1 {
    	public static void main(String[] args) {
    		// 泛型:限制集合中的元素只能儲存某一種的資料型別(jdk>=1.5)
    		/**
    		 * 泛型只在編譯時有效,再底層.class檔案中沒有泛型(泛型的擦除)。
    		 * */
    		Collection c = new ArrayList();
    		List<String> list = new ArrayList<> ();
    		list.add("哈");// Collection 中方法
    		list.add(0, "呼");// ArrayList 中的方法
    		System.out.println(list);// [呼, 哈]
    	}
    }
    
    
    • remove(int index) 根據索引值移除元素
    list.remove(1);
    
    • get(int index) 根據索引值取元素
    list.get(1);
    // 可以通過for迴圈遍歷
    for (int i=0;i<list.size();i++){
    	System.out.println(list.get(i));
    }
    
    • set(int index)
    list.set(1, "呵");
    
    • ListIterator listIterator
    List<String> list = new ArrayList<> ();
    // hashPrevious 檢視前面是否有元素
    while (it.hashPrevious){
    	System.out.println(it.previous());
    }
    // 上面相當於從後往前遍歷。
    // 需要注意是,要想從後往前遍歷,需要先從前往後遍歷以邊,將指標指到最後位置,先執行如下類似邏輯程式碼。
    while (it.hasNext()){
        System.out.println(it.next());
    }
    
  • 四種遍歷方式

    import java.util.List;
    import java.util.ArrayList;
    import java.util.Iterator;
    import java.util.ListIterator;
    
    public class ListTestDemo {
    	public static void main(String[] args) {
    		List<Person> list = new ArrayList<> ();
    		Person p1 = new Person("Tom", '男', 23);
    		Person p2 = new Person("Lucy", '女', 20);
    		list.add(p1);
    		list.add(p2);
    		
    		// 1.轉陣列方式
    		Object[] arr1 = list.toArray();
    		for (int i=0;i<arr1.length;i++) {
    			System.out.println(arr1[i]);
    		}
    		System.out.println("------------------");
    		// 2.迭代器方式
    		Iterator arr2 = list.iterator();
    		while (arr2.hasNext()) {
    			System.out.println(arr2.next());
    		}
    		System.out.println("------------------");
    		// 3.for get方式
    		for (int i=0;i<list.size();i++) {
    			System.out.println(list.get(i));
    		}
    		System.out.println("------------------");
    		// 4.ListIterator
    		ListIterator<Person> it2 = list.listIterator();
    		while (it2.hasNext()) {
    			System.out.println(it2.next());
    		}
    	}
    }
    
    
    class Person{
    	String name;
    	char gender;
    	int age;
    	public Person() {
    		
    	}
    	public Person(String name,char gender,int age) {
    		super();
    		this.name = name;
    		this.age = age;
    		this.gender = gender;
    	}
    	@Override
    	public String toString() {
    		return "Person [name=" + name + ", gender=" + gender + ", age=" + age + "]";
    	}
    }
    
  • 練習:將"張三,18,男;李四,20,男;王五,33,男"切分建立Person物件,並存儲在集合中。

    List<Person> list2 = new ArrayList<> ();
    String  str2 = "張三,18,男;李四,20,男;王五,33,男";
    String[] a1 = str2.split(";");
    for (int i=0; i<a1.length ;i++) {
        String sa = a1[i];
        String[] a2 = sa.split(",");
        String name = a2[0];
        int age = Integer.parseInt(a2[1]);
        char gender = a2[2].charAt(0);
        Person p = new Person(name,gender,age);
        list2.add(p);
        }
        System.out.println(list2);
    
    }
    
  • List中去重:

    • 方式1:新建一個空集合,新增元素前判斷當前序列有沒有該元素,沒有就新增,有就放棄新增。
    • 方式2:在原有集合上,前一個元素和後一個元素進行對比,重複進行刪除操作。刪除會造成序列元素變少,索引值應回到原來索引位置。
    import java.util.ArrayList;
    import java.util.List;
    public class ListquchongDemo {
    	public static void main(String[] args) {
    		List<String> list = new ArrayList<>();
    		list.add("大哥");
    		list.add("二哥");
    		list.add("大哥");
    		list.add("三哥");
    		list.add("大哥");
    		List<String> r = distinct(list);
    		System.out.println(r );// [大哥, 二哥, 三哥]
    		List<String> r2 = distinct2(list);
    		System.out.println(r2);
    	}
    	
    	public static List<String> distinct2(List<String> list) {
    		for (int i=0;i<list.size()-1;i++) {
    			for (int j=i+1; j<list.size();j++) {
    				if (list.get(i).equals(list.get(j))) {
    					list.remove(j);
    					j--;
    				}
    			}
    		}
    		return list;
    	}
    	
    	public static List<String> distinct(List<String> list){
    		// 建立一個新的集合,用於存放不重複的元素
    		List <String> result =new ArrayList<>();
    		// 從要去重的集合中拿到每一個元素,去新的集合中做判斷,如果新的集合中不存在,
    		// 則存入新的集合,如果新的集合存在,就不存。
    		for (int i=0;i<list.size();i++) {
    			String s = list.get(i);
    			if (!result.contains(s)) {
    				result.add(s);
    			}
    		}
    		// 返回結果
    		return result;
    	}
    }
    
    
  • Object型別List去重

    import java.util.List;
    import java.util.ArrayList;
    public class ListTest2 {
    	// 屬性值去重方式,通過重寫hashCode和equals
    	public static void main(String[] args) {
    		List <Personss> list = new ArrayList<> ();
    		list.add(new Personss("張三", 12,'男'));
    		list.add(new Personss("李四", 15,'男'));
    		list.add(new Personss("王二", 19,'男'));
    		list.add(new Personss("張三", 12,'男'));
    		List<Personss> r = distinct(list);
    		System.out.println(list);
    	}
    	public static List<Personss> distinct(List<Personss> list){
    		List <Personss> result = new ArrayList();
    		for (int i=0;i<list.size();i++) {
    			Personss p = list.get(i);
    			if (!result.contains(p)) {
    				result.add(p);
    			}
    		}
    		return result;
    	}
    }
    
    
    class Personss{
    	String name;
    	int age;
    	char gender;
    	public Personss() {}
    	public Personss(String name, int age,char gender) {
    		this.age = age;
    		this.name = name;
    		this.gender = gender;
    	}
    	@Override
    	public int hashCode() {
    		final int prime = 31;
    		int result = 1;
    		result = prime * result + age;
    		result = prime * result + gender;
    		result = prime * result + ((name == null) ? 0 : name.hashCode());
    		return result;
    	}
    	@Override
    	public boolean equals(Object obj) {
    		if (this == obj)
    			return true;
    		if (obj == null)
    			return false;
    		if (getClass() != obj.getClass())
    			return false;
    		Personss other = (Personss) obj;
    		if (age != other.age)
    			return false;
    		if (gender != other.gender)
    			return false;
    		if (name == null) {
    			if (other.name != null)
    				return false;
    		} else if (!name.equals(other.name))
    			return false;
    		return true;
    	}
    	@Override
    	public String toString() {
    		return "Person [name=" + name + ", age=" + age + ", gender=" + gender + "]";
    	}
    }
    
  • LinkList

    • 陣列中,增刪慢,當擴容需要移動元素,消耗大量空間,它內部元素是連續的,並且有索引值,查詢塊。而ArrayList底層是陣列實現的。所以它特點是增刪慢,查詢快。

    • 而連結串列內元素地址不是連續的,內部每個元素為一個節點,每個節點指向下一個元素(儲存下一個元素地址值)。它的特點增刪快,查詢慢。而LinkList底層是連結串列實現的(隨機查詢慢)。

    • LinkList獨有方法

      import java.util.List;
      import java.util.LinkedList;
      public class LinkListDemo {
      	public static void main(String[] args) {
      		LinkedList <Integer> list = new LinkedList<> ();
      		list.add(10);
      		list.add(20);
      		list.add(30);
      		// 頭部新增元素
      		list.addFirst(100);
      		// 尾部新增元素
      		list.addLast(200);
      		System.out.println(list);// [100, 10, 20, 30, 200]
      		// 獲取頭部元素
      		System.out.println(list.getFirst());// 100
      		// 獲取尾部元素
      		System.out.println(list.getLast());// 200
      		// 移除尾部元素
      		list.removeLast();
      		// 移除頭部元素
      		list.removeFirst();
      		System.out.println(list);// [10, 20, 30]
      		
      	}
      }
      

4.for each迴圈

  • for迴圈,從jdk5產生的新特性,主要用於集合或陣列遍歷。

  • 格式:

    for (資料型別 變數名:陣列名/集合名){
    	// 變數名: 集合中的每一個元素
    }
    
  • 示例:

    import java.util.List;
    import java.util.ArrayList;
    import java.util.Collection;
    public class ForeachDemo {
    	public static void main(String[] args) {
    		// 陣列迴圈
    		int[] arr = new int[] {5,12,53,0,11};
    		for (int a:arr) {
    			System.out.println(a);
    		}
    		// List for迴圈
    		List<Integer> list = new ArrayList<> ();
    		list.add(100);
    		list.add(200);
    		list.add(300);
    		for (Integer i:list) {
    			System.out.println(i);
    		}
    		// Collection
    		Collection c = new ArrayList();
    		c.add(123);
    		c.add(456);
    		c.add(789);
    		for (Object o:c) {
    			System.out.println(o);
    		}
    	}
    }
    
    

5.可變引數

  • 用於定義方法的時候不知道定義多少個引數。(jdk5後產生新特性)。

  • 格式:

    修飾符 返回值型別 方法名(資料型別... 變數名){}
    
  • 注意:

    這裡變數起始是一個數組。
    如果一個方法有可變引數,並由多個引數,那麼,可變引數必須是最後一個,一個方法中最多隻能有一個可變引數。
    
  • 示例:

    public class ChangeableParamDemo {
    	public static void main(String[] args) {
    		System.out.println(getSum(1,2,3,4,5,6,7));
    	}
    	public static int getSum(int ...a) {
    		int sum = 0;
    		for (int  i : a) {
    			sum += i;
    		}
    		return sum;
    	}
    }
    

6.集合和陣列相互轉換

  • 集合轉陣列:

    import java.util.List;
    import java.util.ArrayList;
    import java.util.Arrays;
    public class ArrayCollectionDemo {
    	public static void main(String[] args) {
    		// 集合轉陣列。toArray方法
    		List <String> list = new ArrayList<>();
    		list.add("a");
    		list.add("b");
    		list.add("c");
    		Object[] arr = list.toArray();
    		// 陣列轉集合
    		/*
    		 * Arrays工具類中asList方法
    		 * public static <T> List<T> asList(T... a)
    		 * T代表型別
    		 * */
    		// 方式1:
    		List<Integer> list2 = Arrays.asList(1,2,3,4,5,6);
    		System.out.println(list2);// [1, 2, 3, 4, 5, 6]
    		// 方式2:
    		Integer[] arr2 = new Integer[] {3,4,6,11,2,8};
    		List<Integer> list3 = Arrays.asList(arr2);// 得到是Arrays中內部類,該類沒有實現add/remove
    		System.out.println(list3);// [3, 4, 6, 11, 2, 8]
    		// 而使用Arrays.asList 得到集合是一個只讀集合,不能進行add/remove 操作
    		
    		
    		// 通過建立一個新的ArrayList,把元素新增到新的ArrayList就可以進行add/remove操作 
    		List<Integer> list4 = new ArrayList<>(list3);
    		list4.add(300);
    		System.out.println(list4);
    	}
    }
    

7.Set用法

  • Set中元素是不能重複的,並且是無序的(沒有索引).

    Set
    	HashSet:不能保證存入和取出順序
    	LinkedHashSet: 能夠保證存入和取出的順序(連結串列)
    	TreeSet:能夠對內部元素,進行排序
    
  • HashSet:

    public class SetDemo {
    	public static void main(String[] args) {
    		Set<String> set = new HashSet<>();
    		set.add("曹操");
    		set.add("劉備");
    		set.add("張飛");
    		set.add("趙雲");
    		set.add("關羽");
    		set.add("劉備");
    		System.out.println(set);// [關羽, 張飛, 劉備, 曹操, 趙雲]
    	}
    }
    // 可以看到上面Set元素是無序的
    
  • LinkHashSet

    Set<String> set = new LinkedHashSet<>();
    System.out.println(set);// [曹操, 劉備, 張飛, 趙雲, 關羽]
    // 而LinkHashSet是有序的。
    
  • 元素不可重複性判斷是通過hashCode/equals這兩個方法決定的,它是先求出要存的元素的hashCode,看集合是否有元素的hashCode和它相同,如果沒有相同,則直接存入set裡面。如果hashCode相同,再比較equals如果true確實相同,不能存入。false可以存入。

  • set遍歷方式:

    import java.util.HashSet;
    import java.util.Iterator;
    import java.util.Set;
    import java.util.LinkedHashSet;
    public class SetDemo {
    	public static void main(String[] args) {
    		Set<String> set = new HashSet<>();
    		set.add("曹操");
    		set.add("劉備");
    		set.add("張飛");
    		set.add("趙雲");
    		set.add("關羽");
    		set.add("劉備");
    		System.out.println(set);// [曹操, 劉備, 張飛, 趙雲, 關羽]
    		
    		// 1.toArray
    		Object[] array = set.toArray();
    		for (Object o: array) {
    			System.out.println(o);
    		}
    		//2.迭代器
    		Iterator<String> it = set.iterator();
    		while (it.hasNext()) {
    			System.out.println(it.next());
    		}
    		//3.foreach
    		for(String s:set) {
    			System.out.println(s);
    		}
    	}
    }
    
  • 練習建立一個Set 儲存三個元素。列印集合,要求列印是屬性。要求集合中只能儲存兩個元素,使用三種方式遍歷。

    // 重寫 toString 和hashcode 通過屬性去重
    import java.util.HashSet;
    import java.util.Iterator;
    import java.util.Set;
    
    public class SetDemo2 {
    	public static void main(String[] args) {
    		Set<Person> ps = new HashSet<>();
    		
    		ps.add(new Person("張三", 18, '男'));
    		ps.add(new Person("李四", 20, '女'));
    		ps.add(new Person("張三", 18, '男'));
    		System.out.println(ps);
    	}
    }
    
    class Person{
    	String name;
    	int age;
    	char gender;
    	public Person() {
    		
    	}
    	public Person(String name,int age, char gender) {
    		this.name = name;
    		this.age = age;
    		this.gender = gender;
    	}
    	@Override
    	public String toString() {
    		return "Person [name=" + name + ", age=" + age + ", gender=" + gender + "]";
    	}
    	@Override
    	public int hashCode() {
    		final int prime = 31;
    		int result = 1;
    		result = prime * result + age;
    		result = prime * result + gender;
    		result = prime * result + ((name == null) ? 0 : name.hashCode());
    		return result;
    	}
    	@Override
    	public boolean equals(Object obj) {
    		if (this == obj)
    			return true;
    		if (obj == null)
    			return false;
    		if (getClass() != obj.getClass())
    			return false;
    		Person other = (Person) obj;
    		if (age != other.age)
    			return false;
    		if (gender != other.gender)
    			return false;
    		if (name == null) {
    			if (other.name != null)
    				return false;
    		} else if (!name.equals(other.name))
    			return false;
    		return true;
    	}
    }
    
  • Set生成不重複隨機數

    import java.util.HashSet;
    import java.util.Random;
    import java.util.Set;
    
    public class SetDemo3 {
    	public static void main(String[] args) {
    		Random r = new Random();
    		Set<Integer> set = new HashSet<>();
    		while (set.size() != 10) {
    			int i = r.nextInt(20) + 1;
    			set.add(i);
    		}
    		System.out.println(set);
    	}
    }
    
    
  • 利用Set實現List去重。

    
    import java.util.ArrayList;
    import java.util.HashSet;
    import java.util.List;
    import java.util.Set;
    
    public class SetDemo4 {
    	public static void main(String[] args) {
    		List<String> list = new ArrayList<> ();
    		list.add("大哥");
    		list.add("二哥");
    		list.add("大哥");
    		list.add("三哥");
    		System.out.println(distinct(list));
    	}
    	public static List<String> distinct(List<String> list){
    		Set<String> set = new HashSet<> ();
    		// 將list元素新增set去重
    		set.addAll(list);
    		// 清空list
    		list.clear();
    		// 將去重set中元素新增list中
    		list.addAll(set);
    		return list;
    	}
    }
    

8.Map

  • Map是雙列集合根介面。

  • 將鍵對映到值的物件

  • 一個對映不能包含重複的鍵。

  • 每個鍵最多隻能對映到一個值key=value

  • Map介面和Collection介面的不同,Map是雙列的,Collection是單列的。

  • Map的鍵唯一,Collection的子體系Set是唯一的。

  • Map集合的資料結構值針對鍵有效,跟值無關。

  • Map分類

    HashMap: key不能重複,但是可以為null,不能保證key存入和取出順序。
    LinkedHashMap:可以保證key存入和取出的順序。
    
  • Map中方法

    put(k key, v value) 新增元素
    remove(Object key) 移除元素 對應鍵值對
    void clear()  清空map
    boolean containsKey(Object key)  是否包含key
    boolean containsValue(Object value) 是否包含value
    boolean isEmpty() 是否為空(長度是否為0)
    int size()  鍵值對的個數
    
  • 示例:

    import java.util.HashMap;
    import java.util.Map;
    
    public class MapDemo1 {
    	public static void main(String[] args) {
    		Map<Integer,String> map = new HashMap<>();
    		map.put(5, "數字5");
    		map.put(6, "數字6");
    		map.put(7, "數字7");
    		String result1 = map.put(8, "數字8");
    		System.out.println(result1);// null
    		String result2 = map.put(7, "number seven");
    		System.out.println(result2);// 數字7
    		System.out.println(map);// {5=數字5, 6=數字6, 7=數字7}
    		
    		System.out.println(map.remove(9));// null
    		System.out.println(map.remove(7));// number seven
    		System.out.println(map.containsKey(7));//false
    		System.out.println(map.containsValue("數字6"));// true
    		map.clear();
    		System.out.println(map.isEmpty());// true
    	}
    }
    
  • HashMap遍歷

    import java.util.Collection;
    import java.util.HashMap;
    import java.util.Map;
    import java.util.Set;
    
    public class MapCDemo2 {
    	public static void main(String[] args) {
    		Map<Integer,String> map = new HashMap<>();
    		map.put(1, "one");
    		map.put(2, "two");
    		map.put(3, "three");
    		map.put(4, "four");
    		// 1.map遍歷方式:獲取所有key   keySet:
    		// 獲取所有key
    		Set<Integer> keySet = map.keySet();
    		for (Integer key : keySet) {
    			// 迴圈所有key,通過get方法列印所有value
    			System.out.println(map.get(key));
    		}
    		// 2.map遍歷方式:獲取所有鍵和值  entrySet
    		Set<Map.Entry<Integer,String>> entrySet = map.entrySet();
    		for (Map.Entry<Integer, String> entry : entrySet) {
    			System.out.println(entry.getKey() + ":" +entry.getValue());
    		}
    		// 3.map遍歷方式:獲取所有value  values
    		Collection<String> values = map.values();
    		for (String s : values) {
    			System.out.println(s);
    		}
    	}
    }
    
    
    • 上述遍歷方式也可以通過迭代器寫
    import java.util.Map.Entry;
    import java.util.Iterator;
    
    
    Iterator<Entry<Integer,String>> it = entrySet.iterator();
        while(it.hasNext()) {
            Entry<Integer,String> entry = it.next();
            System.out.println(entry.getKey() + ":" + entry.getValue());
    }
    
  • 練習:統計字串個數:

    
    import java.util.HashMap;
    import java.util.Map;
    import java.util.Scanner;
    
    public class MapDemo3 {
    	public static void main(String[] args) {
    		
    		Map<Character,Integer> map = new HashMap<>();
    		Scanner sc = new Scanner(System.in);
    		System.out.println("請輸入字串:");
    		String str = sc.next();
    		for (int i=0;i<str.length();i++) {
    			char ch = str.charAt(i);
    			// 根據key去map中取value,如果有值就返回value,如果沒有返回預設值。
    			Integer count = map.getOrDefault(ch, 0);
    			count++;
    			map.put(ch, count);
    //			Integer count = map.get(ch);
    //			if (count == null) {
    //				// 字元第一處出現
    //				map.put(ch, 1);
    //			}else {
    //				// 不是第一次出現
    //				count++;
    //				map.put(ch, count);
    //			}
    		}
    		System.out.println(map);
    	}
    }
    
    // 請輸入字串:
    // asdaerteatsfcx
    // {a=3, r=1, s=2, c=1, d=1, t=2, e=2, f=1, x=1}
    
  • HashMap實現原理:

    • HashMap是通過雜湊表(散列表)實現的。 陣列+連結串列。

      Map map = new HashMap();
      // 它的底層是陣列+連結串列,主體是陣列。
      當執行map.put(1,a);  key=1 首先求出hashCode, 對hashCode進行hash運算,運算結果代表它儲存陣列中的位置(bucket)。 但是當陣列儲存bucket位置中已經存在元素(hash相同,存在hash衝撞),它會對比它們之間key,如果不相同,它會用連結串列連線當前位置所有元素,後進來元素放在頭上(頭插法)。如果比較key相同,就把對應value值進行替換。