1. 程式人生 > 實用技巧 >Java之Collections、Set、Map

Java之Collections、Set、Map

第一章 Collections類

知識點-- Collections常用功能

目標

  • 能夠使用集合工具類Collections

路徑

  • 程式碼演示

講解

  • java.utils.Collections是集合工具類,用來對集合進行操作。

    常用方法如下:

  • public static void shuffle(List<?> list) :打亂集合順序。

  • public static <T> void sort(List<T> list):將集合中元素按照預設規則排序。

  • public static <T> void sort(List<T> list,Comparator<? super T> com )

    :將集合中元素按照指定規則排序。

程式碼演示:

 /**
     * public static void shuffle(List<?> list):打亂集合中元素的順序。
     */
    private static void method01() {
        // 建立一個List集合物件,限制集合中元素型別為Integer
        List<Integer> list = new ArrayList<>();
        // 往集合中新增一些元素
        list.add(300);
        list.add(100);
        list.add(200);
        list.add(500);
        list.add(400);
        System.out.println("打亂順序之前:"+list);// 打亂順序之前:[300, 100, 200, 500, 400]

        // 隨機打亂集合中元素的順序:public static void shuffle(List<?> list)
        Collections.shuffle(list);
        System.out.println("打亂順序之後:"+list);
    }
    /**
     *  public static <T> void sort(List<T> list):將集合中元素按照預設規則排序。
     *  集合中的元素為系統類的物件
     */
    private static void method02() {
        // 建立一個List集合物件,限制集合中元素型別為Integer
        List<Integer> list = new ArrayList<>();
        // 往集合中新增一些元素
        list.add(300);
        list.add(100);
        list.add(200);
        list.add(500);
        list.add(400);
        System.out.println("排序之前的集合:"+list);// 打亂順序之前:[300, 100, 200, 500, 400]

        // 將集合中元素按照預設規則排序: public static <T> void sort(List<T> list)
        Collections.sort(list);
        System.out.println("排序之後的集合:"+list);// 排序之後的集合:[100, 200, 300, 400, 500]
    }

我們的集合按照預設的自然順序進行了排列,如果想要指定順序那該怎麼辦呢?

知識點-- Comparator比較器

目標

  • 能夠使用Comparator比較器進行排序

路徑

  • 程式碼演示

講解

 public static void main(String[] args) {
        /*
            Collections常用功能:
                - public static void shuffle(List<?> list):打亂集合中元素的順序。
                - public static <T> void sort(List<T> list):將集合中元素按照預設規則排序。
                    預設規則: 事先寫好的規則
                    對集合中的元素按照預設規則排序,要求該集合元素所屬的類實現Comparable介面,重寫compareTo()方法
                    然後在compareTo()方法中指定排序的預設規則

                - public static <T> void sort(List<T> list,Comparator<? super T> ):將集合中元素按照指定規則排序。
                    指定規則: 自己定義的規則
                    引數Comparator<T>介面:也稱比較器介面,用來指定排序的規則
         */
        // 建立一個List集合物件,限制集合中元素型別為Integer
        List<Integer> list = new ArrayList<>();
        // 往集合中新增一些元素
        list.add(300);
        list.add(100);
        list.add(200);
        list.add(500);
        list.add(400);
        System.out.println("排序之前的集合:"+list);// 打亂順序之前:[300, 100, 200, 500, 400]

     	// 300 100 200 500 400
        //  300  
        // 對list集合指定規則排序: 降序
        Collections.sort(list, new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                // 指定排序規則 
                // 前減後:升序
                // 後減前:降序
                // 前:第一個引數  o1
                // 後:第二個引數  o2
                return o2 - o1;
            }
        });

        System.out.println("排序之後的集合:"+list);// 排序之後的集合:[500, 400, 300, 200, 100]

        // 對list集合指定規則排序: 升序
        Collections.sort(list, new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                // 指定排序規則
                // 前減後:升序
                // 後減前:降序
                // 前:第一個引數  o1
                // 後:第二個引數  o2
                return o1 - o2;
            }
        });
        System.out.println("排序之後的集合:"+list);// 排序之後的集合:[100, 200, 300, 400, 500]

    }

知識點-- 可變引數

目標

  • 能夠使用可變引數

路徑

  • 可變引數的使用
  • 注意事項
  • 應用場景: Collections

講解

可變引數的使用

JDK1.5之後,如果我們定義一個方法需要接受多個引數,並且多個引數型別一致,我們可以對其簡化.

格式:

修飾符 返回值型別 方法名(引數型別... 形參名){  }

程式碼演示:

 public class Demo {
    public static void main(String[] args) {
        // 可變引數的語法
        /*int[] arr = {10, 20, 30, 40, 50, 60};

        // 呼叫method1方法
        method1(10, 20, 30, 40, 50);
        // 呼叫method2方法
        method2(arr);
        method2(10, 20, 30, 40, 50, 60);
        //
        method3(arr);
        method3(10, 20, 30, 40, 50, 60);

        method4(10,"jack","rose");*/
    }

    public static void method4(int num,String... str){

    }

    // 定義一個方法,可以接收5個int型別的引數
    public static void method3(int[] arr) {
        for (int i : arr) {
            System.out.println(i);
        }
        System.out.println(arr[0]);
    }


    // 定義一個方法,可以接收5個int型別的引數
    public static void method2(int... num) {
        for (int i : num) {
            System.out.println(i);
        }
        System.out.println(num[0]);
    }

    // 定義一個方法,可以接收5個int型別的引數
    public static void method1(int num1, int num2, int num3, int num4, int num5) {

    }
}

注意事項

​ 1.一個方法只能有一個可變引數

​ 2.如果方法中有多個引數,可變引數要放到最後。

應用場景: Collections

​ 在Collections中也提供了新增一些元素方法:

public static <T> boolean addAll(Collection<T> c, T... elements) :往集合中新增一些元素。

程式碼演示:

public class CollectionsDemo {
	public static void main(String[] args) {
      ArrayList<Integer> list = new ArrayList<Integer>();
      //原來寫法
      //list.add(12);
      //list.add(14);
      //list.add(15);
      //list.add(1000);
      //採用工具類 完成 往集合中新增元素  
      Collections.addAll(list, 5, 222, 1,2);
      System.out.println(list);
}

第二章 Set介面

知識點--Set介面介紹

目標

  • Set介面介紹

路徑

  • Set介面

講解

 Set介面:也稱Set集合,但凡是實現了Set介面的類都叫做Set集合
        特點:元素無索引,元素存取無序,元素不可重複(唯一)
        實現類:
              HashSet集合:元素無索引,元素存取無序,元素不可重複(唯一)
              LinkedHashSet集合:元素無索引,元素存取有序,元素不可重複(唯一)
              TreeSet集合:元素無索引,元素存取無序,元素不可重複(唯一),元素可排序
 注意:
        1.Set集合並沒有特有的功能,都是使用Collection父介面中的方法
        2.Set集合元素無索引,所以遍歷方式只能是:迭代器,增強for迴圈

知識點--HashSet集合

目標

  • 能夠說出HashSet集合的特點

路徑

  • HashSet集合的特點

講解

java.util.HashSetSet介面的一個實現類,它所儲存的元素是不可重複的,並且元素都是無序的(即存取順序不能保證不一致)。

我們先來使用一下Set集合儲存,看下現象,再進行原理的講解:

public class Test {
    public static void main(String[] args) {
        /*
          HashSet集合的特點:
            HashSet集合(類): 儲存資料的資料結構,雜湊表結構,元素唯一,元素無索引,元素存取無序
         */
        // 建立一個HashSet集合,限制集合中元素的型別為String型別
        HashSet<String> set = new HashSet<>();

        // 往集合中新增元素
        set.add("nba");
        set.add("cba");
        set.add("bac");
        set.add("abc");
        set.add("nba");

        System.out.println(set);// [cba, abc, bac, nba]
    }
}

知識點--HashSet集合儲存資料的結構(雜湊表)

目標

  • 雜湊表底層結構以及HashSet保證元素唯一原理

路徑

  • 雜湊表底層結構
  • HashSet保證元素唯一原理

講解

雜湊表底層結構

JDK1.8之前,雜湊表底層採用陣列+連結串列實現,即使用陣列處理衝突,同一hash值的連結串列都儲存在一個數組裡。但是當位於一個桶中的元素較多,即hash值相等的元素較多時,通過key值依次查詢的效率較低。而JDK1.8中,雜湊表儲存採用陣列+連結串列+紅黑樹實現,當連結串列長度超過閾值(8)時,將連結串列轉換為紅黑樹,這樣大大減少了查詢時間。

簡單的來說,雜湊表是由陣列+連結串列+紅黑樹(JDK1.8增加了紅黑樹部分)實現的,如下圖所示。

HashSet保證元素唯一原理
HashSet集合保證元素唯一的原理:底層是雜湊表結構,雜湊表保證元素唯一依賴於hashCode()和equals方法();
1.當HashSet集合儲存元素的時候,就會呼叫該元素的hashCode()方法計算雜湊值
2.判斷該雜湊值位置上,是否有相同雜湊值的元素
3.如果該雜湊值位置上沒有相同雜湊值的元素,那麼就直接儲存
4.如果該雜湊值位置上有相同雜湊值的元素,那麼就產生了雜湊衝突
5.如果產生了雜湊衝突,就得呼叫該元素的equals()方法與該雜湊值位置上的所有元素進行一一比較:
  如果該雜湊值位置上有任意一個元素與該元素相等,那麼就不儲存
  如果該雜湊值位置上所有元素與該元素都不相等,那麼就直接儲存
補充:
     Object類: hashCode()和equals()方法;
              hashCode():Object類中的hashCode()方法是根據地址值計算雜湊值
              equals方法():Object類中的equals()方法是比較地址值
public class Demo {
    public static void main(String[] args) {
        // 建立一個HashSet集合,限制集合中元素的型別為String
        HashSet<String> set = new HashSet<>();

        // 往集合中新增一些元素
        set.add("nba");
        set.add("cba");
        set.add("bac");
        set.add("abc");
        set.add("nba");

        // 遍歷列印集合
        for (String e : set) {
            System.out.println(e);// cba abc  bac  nba
        }

        System.out.println("nba".hashCode());// nba:108845
        System.out.println("cba".hashCode());// cba:98274
        System.out.println("bac".hashCode());// bac:97284
        System.out.println("abc".hashCode());// abc:96354
    }
}

知識點-- HashSet儲存自定義型別元素

1.目標

  • 使用HashSet集合儲存自定義元素

2.路徑

  • 程式碼演示

3.講解

給HashSet中存放自定義型別元素時,需要重寫物件中的hashCode和equals方法,建立自己的比較方式,才能保證HashSet集合中的物件唯一.

public class Person{
    /**
     * 姓名
     */
    public String name;
    /**
     * 年齡
     */
    public int age;

    public Person() {
    }

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Person person = (Person) o;
        return age == person.age &&
                Objects.equals(name, person.name);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name, age);
    }
}

建立測試類:

public class Demo {
    public static void main(String[] args) {
        // 建立多個Person物件
        Person p1 = new Person("張三", 18);
        Person p2 = new Person("李四", 38);
        Person p3 = new Person("王五", 28);
        Person p4 = new Person("張三", 18);

        // 建立HashSet集合物件,限制集合中元素的型別為Person
        HashSet<Person> set = new HashSet<>();

        // 往集合中新增Person物件
        set.add(p1);
        set.add(p2);
        set.add(p3);
        set.add(p4);

        // 遍歷列印集合中的元素
        for (Person p : set) {
            System.out.println(p);
        }

        System.out.println(p1.hashCode());
        System.out.println(p2.hashCode());
        System.out.println(p3.hashCode());
        System.out.println(p4.hashCode());
    }
}

知識點-- LinkedHashSet

目標

  • 使用LinkedHashSet保證元素怎麼存就怎麼取,即存取有序

路徑

  • 程式碼演示

講解

我們知道HashSet保證元素唯一,可是元素存放進去是沒有順序的,那麼我們要保證有序,怎麼辦呢?

在HashSet下面有一個子類java.util.LinkedHashSet,它是連結串列和雜湊表組合的一個數據儲存結構。

演示程式碼如下:

public class LinkedHashSetDemo {
	public static void main(String[] args) {
		Set<String> set = new LinkedHashSet<String>();
		set.add("bbb");
		set.add("aaa");
		set.add("abc");
		set.add("bbc");
        Iterator<String> it = set.iterator();
		while (it.hasNext()) {
			System.out.println(it.next());
		}
	}
}
結果:
  bbb
  aaa
  abc
  bbc

知識點-- TreeSet集合

目標

  • 知道使用TreeSet集合的特點並能夠使用TreeSet集合

路徑

  • 程式碼演示

講解

特點

TreeSet集合是Set介面的一個實現類,底層依賴於TreeMap,是一種基於紅黑樹的實現,其特點為:

  1. 元素唯一
  2. 元素沒有索引
  3. 使用元素的自然順序對元素進行排序,或者根據建立 TreeSet 時提供的 Comparator 比較器
    進行排序,具體取決於使用的構造方法:
public TreeSet():								根據其元素的自然排序進行排序
public TreeSet(Comparator<E> comparator):    根據指定的比較器進行排序

演示

案例演示自然排序(20,18,23,22,17,24,19):

public static void main(String[] args) {
	//無參構造,預設使用元素的自然順序進行排序
	TreeSet<Integer> set = new TreeSet<Integer>();
	set.add(20);
	set.add(18);
  	set.add(23);
  	set.add(22);
  	set.add(17);
  	set.add(24);
  	set.add(19);
  	System.out.println(set);
}

控制檯的輸出結果為:
[17, 18, 19, 20, 22, 23, 24]

案例演示比較器排序(20,18,23,22,17,24,19):

public static void main(String[] args) {
  	//有參構造,傳入比較器,使用比較器對元素進行排序
  	TreeSet<Integer> set = new TreeSet<Integer>(new Comparator<Integer>() {
    	@Override
    	public int compare(Integer o1, Integer o2) {
      		//元素前 - 元素後 : 升序
      		//元素後 - 元素前 : 降序
      		return o2 - o1;
    	}
  	});
  	set.add(20);
  	set.add(18);
  	set.add(23);
  	set.add(22);
  	set.add(17);
  	set.add(24);
  	set.add(19);
  	System.out.println(set);
}

控制檯的輸出結果為:
[24, 23, 22, 20, 19, 18, 17]

第三章 Map集合

知識點-- Map概述

目標

  • 能夠說出Map集合的特點

路徑

  • 圖文演示

講解

 Map集合的概述:
       Map<K,V>介面概述:也稱Map集合,是所有雙列集合的頂層父介面,K用來限制鍵的型別,V用來限制值的型別
       Map集合的特點:
                    1.Map集合儲存元素是以鍵值對的形式儲存,也就是說每一個鍵值對都有鍵和值
                    2.通過鍵取值
                    3.Map集合中的鍵不能重複,如果鍵重複了,那麼值就會覆蓋
                    4.Map集合中的值是可以重複
       Map集合的實現類:
                    HashMap類:鍵唯一,鍵值對存取無序, 由雜湊表保證鍵唯一
                    LinkedHashMap類:鍵唯一,鍵值對存取有序,由雜湊表保證鍵唯一,由連結串列保證鍵值對存取有序
                    TreeMap類:鍵唯一,可以對鍵值對進行排序

知識點-- Map的常用方法

目標

  • 使用Map的常用方法

路徑

  • 程式碼演示

講解

Map介面中定義了很多方法,常用的如下:

  • public V put(K key, V value): 把指定的鍵與指定的值新增到Map集合中。
  • public V remove(Object key): 把指定的鍵 所對應的鍵值對元素 在Map集合中刪除,返回被刪除元素的值。
  • public V get(Object key) 根據指定的鍵,在Map集合中獲取對應的值。
  • public boolean containsKey(Object key):判斷該集合中是否有此鍵
  • public Set<K> keySet(): 獲取Map集合中所有的鍵,儲存到Set集合中。
  • public Collection<V> values() 獲取Map集合中所有的值,儲存到Collection集合中
  • public Set<Map.Entry<K,V>> entrySet(): 獲取到Map集合中所有的鍵值對物件的集合(Set集合)。

Map介面的方法演示

public class Test {
    public static void main(String[] args) {
        /*
            Map<K,V>的常用方法:
                - public V put(K key, V value):  把指定的鍵與指定的值新增到Map集合中。
                - public  int size()  獲取集合中鍵值對的個數(Map集合的大小)
                - public V remove(Object key): 把指定的鍵 所對應的鍵值對元素 在Map集合中刪除,返回被刪除元素的值。
                - public V get(Object key) 根據指定的鍵,在Map集合中獲取對應的值。
                - public boolean containsKey(Object key):判斷該集合中是否有此鍵
                - public  boolean containsValue(Object value)  判斷該集合中是否有此值

                - public Set<K> keySet(): 獲取Map集合中所有的鍵,儲存到Set集合中。
                - public Collection<V> values() 獲取Map集合中所有的值,儲存到Collection集合中。

                - public Set<Map.Entry<K,V>> entrySet(): 獲取到Map集合中 所有的 鍵值對物件 的集合(Set集合)。
                Entry<K, V>: 一種資料型別,表示鍵值對物件型別
                由於 Entry<K, V> 是Map介面的成員內部介面,所以表示的時候這麼寫Map.Entry<K,V>
                Entry介面中的方法:
                    K getKey();  獲取鍵值對物件的鍵
                    V getValue(); 獲取鍵值對物件的值

                鍵值對:    兩個物件
                鍵值對物件: 一個物件(包裝了鍵值對後的一個物件)
         */
        Map<String, String> map = new HashMap<>();
        // 往集合中新增鍵值對
        map.put("黃曉明", "楊穎");
        map.put("文章", "馬伊琍");
        map.put("謝霆鋒", "王菲");
        map.put("李亞鵬", "王菲");

        // public Set<Map.Entry<K,V>> entrySet(): 獲取到Map集合中 所有的 鍵值對物件 的集合(Set集合)。
        Set<Map.Entry<String, String>> entrySet = map.entrySet();

        System.out.println(entrySet);
        System.out.println(entrySet.size());
    }

    /*
      - public Set<K> keySet(): 獲取Map集合中所有的鍵,儲存到Set集合中。
      - public Collection<V> values() 獲取Map集合中所有的值,儲存到Collection集合中。
     */
    private static void method02() {
        // 建立Map集合,限制鍵的型別為String,限制值的型別為String
        Map<String, String> map = new HashMap<>();
        // 往集合中新增鍵值對
        map.put("黃曉明", "楊穎");
        map.put("文章", "馬伊琍");
        map.put("謝霆鋒", "王菲");
        map.put("李亞鵬", "王菲");

        //  public Set<K> keySet(): 獲取Map集合中所有的鍵,儲存到Set集合中。
        Set<String> keys = map.keySet();
        System.out.println(keys);// [文章, 謝霆鋒, 李亞鵬, 黃曉明]

        // public Collection<V> values() 獲取Map集合中所有的值,儲存到Collection集合中。
        Collection<String> values = map.values();
        System.out.println(values);// [馬伊琍, 王菲, 王菲, 楊穎]
    }

    /*
        - public V put(K key, V value):  把指定的鍵與指定的值新增到Map集合中。
        - public  int size()  獲取集合中鍵值對的個數(Map集合的大小)
        - public V remove(Object key): 把指定的鍵 所對應的鍵值對元素 在Map集合中刪除,返回被刪除元素的值。
        - public V get(Object key) 根據指定的鍵,在Map集合中獲取對應的值。
        - public boolean containsKey(Object key):判斷該集合中是否有此鍵
        - public  boolean containsValue(Object value)  判斷該集合中是否有此值
     */
    private static void method01() {
        // 建立Map集合,限制鍵的型別為String,限制值的型別為String
        Map<String, String> map = new HashMap<>();

        // public V put(K key, V value) 把指定的鍵與指定的值新增到Map集合中。
        map.put("黃曉明","楊穎");
        String value1 = map.put("文章", "馬伊琍");// null
        String value2 = map.put("文章", "姚笛");// 馬伊琍
        map.put("謝霆鋒", "王菲");
        System.out.println("value1:"+value1);
        System.out.println("value2:"+value2);
        System.out.println(map);// {文章=姚笛, 謝霆鋒=王菲, 黃曉明=楊穎}

        //  public  int size()  獲取集合中鍵值對的個數(Map集合的大小)
        System.out.println(map.size());// 3

        System.out.println("=================================");
        // public V remove(Object key); 根據指定的鍵,刪除集合中對應的鍵值對
        String value3 = map.remove("文章");
        System.out.println("value3:"+value3);// 姚笛
        System.out.println(map);// {謝霆鋒=王菲, 黃曉明=楊穎}


        // public V get(Object key) 根據指定的鍵,在Map集合中獲取對應的值。
        String value4 = map.get("謝霆鋒");
        System.out.println("value4:"+value4);// 王菲

        System.out.println("======================");
        // public boolean containKey(Object key):判斷該集合中是否有此鍵
        System.out.println(map.containsKey("謝霆鋒"));// true
        System.out.println(map.containsKey("李亞鵬"));// false

        //  public  boolean containsValue(Object value)  判斷該集合中是否有此值
        System.out.println(map.containsValue("王菲"));// true
        System.out.println(map.containsValue("張柏芝"));// false
    }
}

tips:

使用put方法時,若指定的鍵(key)在集合中沒有,則沒有這個鍵對應的值,返回null,並把指定的鍵值新增到集合中;

若指定的鍵(key)在集合中存在,則返回值為集合中鍵對應的值(該值為替換前的值),並把指定鍵所對應的值,替換成指定的新值。

知識點--Map的遍歷

目標

  • 使用Map的遍歷

路徑

  • 方式1:鍵找值方式
  • 方式2:鍵值對方式

講解

方式1:鍵找值方式

通過元素中的鍵,獲取鍵所對應的值

分析步驟:

  1. 獲取Map中所有的鍵,由於鍵是唯一的,所以返回一個Set集合儲存所有的鍵。方法提示:keyset()
  2. 遍歷鍵的Set集合,得到每一個鍵。
  3. 根據鍵,獲取鍵所對應的值。方法提示:get(K key)
public class Demo {
    public static void main(String[] args) {
        // 建立Map集合物件,限制鍵的型別為String,值的型別為String
        Map<String, String> map = new HashMap<>();
        // 往map集合中新增鍵值對
        map.put("黃曉明", "楊穎");
        map.put("文章", "馬伊琍");
        map.put("謝霆鋒", "王菲");

        // 遍歷map集合
        // 獲取集合中所有的鍵  Set<K> keySet()方法
        Set<String> keys = map.keySet();
        // 遍歷所有的鍵的集合
        for (String key : keys) {
            // 在迴圈中,根據鍵找值 V get(K key)方法
            String value = map.get(key);
            System.out.println("鍵:"+key+",值:"+value);
        }
    }
}

方式2:鍵值對方式

Entry<K,V>介面:簡稱Entry項,表示鍵值對物件,用來封裝Map集合中的鍵值對
Entry<K,V>介面:是Map介面中的內部介面,在外部使用的時候是這樣表示: Map.Entry<K,V>

Map集合中提供了一個方法來獲取所有鍵值對物件:
            public Set<Map.Entry<K,V>> entrySet()

根據鍵值對對物件獲取鍵和值:
            - public K getKey():獲取Entry物件中的鍵。
            - public V getValue():獲取Entry物件中的值。

Map遍歷方式二:根據鍵值對物件的方式
            1.獲取集合中所有鍵值對物件,以Set集合形式返回。  Set<Map.Entry<K,V>> entrySet()
            2.遍歷所有鍵值對物件的集合,得到每一個鍵值對(Entry)物件。
            3.在迴圈中,可以使用鍵值對對物件獲取鍵和值   getKey()和getValue()
public class Demo {
    public static void main(String[] args) {
        // 建立Map集合物件,限制鍵的型別為String,值的型別為String
        Map<String, String> map = new HashMap<>();
        // 往map集合中新增鍵值對
        map.put("黃曉明", "楊穎");
        map.put("文章", "馬伊琍");
        map.put("謝霆鋒", "王菲");

        // 獲取集合中所有鍵值對物件  Set<Map.Entry<K,V>> entrySet()
        Set<Map.Entry<String, String>> entrySet = map.entrySet();

        // 遍歷所有鍵值對物件的集合
        for (Map.Entry<String, String> entry : entrySet) {
            // 在迴圈中,可以使用鍵值對對物件獲取鍵和值   getKey()和getValue()
            String key = entry.getKey();
            String value = entry.getValue();
            System.out.println("鍵:"+key+",值:"+value);
        }
    }
}

知識點-- HashMap儲存自定義型別

目標

  • 使用HashMap儲存自定義型別

路徑

  • 程式碼演示

講解

練習:每位學生(姓名,年齡)都有自己的家庭住址。那麼,既然有對應關係,則將學生物件和家庭住址儲存到map集合中。學生作為鍵, 家庭住址作為值。

注意,學生姓名相同並且年齡相同視為同一名學生。

編寫學生類:

public class Student {
    /**
     * 姓名
     */
    public String name;
    /**
     * 年齡
     */
    public int age;

    public Student() {
    }

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Student student = (Student) o;
        return age == student.age &&
                Objects.equals(name, student.name);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name, age);
    }
}

編寫測試類:

public class Demo {
    public static void main(String[] args) {
        // 建立Map集合,指定鍵的型別為Student,值的型別為String
        HashMap<Student,String> map = new HashMap<>();

        // 建立多個學生物件
        Student stu1 = new Student("張三", 18);
        Student stu2 = new Student("李四", 38);
        Student stu3 = new Student("王五", 28);
        Student stu4 = new Student("張三", 18);

        // 把學生物件作為鍵,家庭地址作為值,儲存到map集合中
        map.put(stu1,"北京");
        map.put(stu2,"上海");
        map.put(stu3,"深圳");
        map.put(stu4,"廣州");

        // 列印map集合
        System.out.println(map);
        System.out.println(map.size());// 3
    }
}
  • 當給HashMap中存放自定義物件時,如果自定義物件作為key存在,這時要保證物件唯一,必須複寫物件的hashCode和equals方法(如果忘記,請回顧HashSet存放自定義物件)。
  • 如果要保證map中存放的key和取出的順序一致,可以使用java.util.LinkedHashMap集合來存放。

知識點--LinkedHashMap介紹

目標

  • 我們知道HashMap保證成對元素唯一,並且查詢速度很快,可是成對元素存放進去是沒有順序的,那麼我們要保證有序,還要速度快怎麼辦呢?

路徑

  • LinkedHashMap

講解

  • 通過連結串列結構可以保證元素的存取順序一致;
  • 通過雜湊表結構可以保證的鍵的唯一、不重複,需要重寫鍵的hashCode()方法、equals()方法。
public class Test {
    public static void main(String[] args) {
        /*
            LinkedHashMap介紹:
                 LinkedHashMap集合(類): 元素無索引,鍵唯一,鍵值對元素存取有序
                                 儲存資料採用的是雜湊表+連結串列結構
                                 由雜湊表保證鍵唯一,由連結串列保證鍵值對元素存取有序
                                  如果鍵是自定義型別的類,為了保證鍵唯一,就得重寫hashCode()和equals()方法
         */
        // 建立LinkedHashMap集合,限制鍵的型別為String型別,限制值的型別為String型別
        LinkedHashMap<String, String> map = new LinkedHashMap<>();
        //HashMap<String, String> map = new HashMap<>();

        // 往集合中新增鍵值對
        map.put("黃曉明", "楊穎");
        map.put("文章", "馬伊琍");
        map.put("謝霆鋒", "王菲");
        map.put("李亞鵬", "王菲");
        map.put("文章", "姚笛");

        // 列印集合
        System.out.println(map);
    }
}

知識點--TreeMap集合

目標

  • 使用TreeMap集合

路徑

  • TreeMap介紹
  • 構造方法

講解

TreeMap介紹

TreeMap集合和Map相比沒有特有的功能,底層的資料結構是紅黑樹;可以對元素的進行排序,排序方式有兩種:自然排序比較器排序;到時使用的是哪種排序,取決於我們在建立物件的時候所使用的構造方法;

構造方法

public TreeMap()									使用自然排序
public TreeMap(Comparator<? super K> comparator) 	   通過比較器指定規則排序

案例演示

public class Test {
    public static void main(String[] args) {
        /*
            TreeMap集合:
                TreeMap集合(類):元素無索引,鍵唯一,鍵值對元素根據鍵排序
                                   儲存資料採用的是紅黑樹結構,由紅黑樹結構保證鍵唯一
                構造方法:
                    TreeMap(); 按照鍵的預設排序規則對鍵值對進行排序
                            要求: 集合中鍵所屬的類要實現Comparable介面,重寫compareTo方法,在該方法中寫好預設的排序規則
                    TreeMap(Comparator<? super K> comparator):按照鍵的指定排序規則對鍵值對進行排序

               鍵為自定義型別的類,課後自己去玩玩
         */
        // 按照鍵的預設規則排序:
        // 建立TreeMap集合,限制鍵的型別為Integer,限制值的型別為String
        TreeMap<Integer, String> map = new TreeMap<>();

        // 往集合中新增鍵值對
        map.put(300, "黃曉明");
        map.put(100, "劉德華");
        map.put(200, "黎明");
        map.put(500, "張學友");
        map.put(400, "郭富城");
        // 列印集合
        System.out.println(map);// {100=劉德華, 200=黎明, 300=黃曉明, 400=郭富城, 500=張學友}

        System.out.println("+++++++++++++++++++++++++++++++++");
        // 按照鍵的指定規則排序:
        // 建立TreeMap集合,限制鍵的型別為Integer,限制值的型別為String
        TreeMap<Integer, String> map2 = new TreeMap<>(new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                // 指定規則: 前減後 升序  後減前 降序
                return o2 - o1;
            }
        });

        // 往集合中新增鍵值對
        map2.put(300, "黃曉明");
        map2.put(100, "劉德華");
        map2.put(200, "黎明");
        map2.put(500, "張學友");
        map2.put(400, "郭富城");

        System.out.println(map2);// {500=張學友, 400=郭富城, 300=黃曉明, 200=黎明, 100=劉德華}
    }
}

案例-- Map集合練習

需求

  • 輸入一個字串,獲取該字串中每個字元出現次數。

分析

  • 獲取一個字串物件
  • 建立一個Map集合,鍵代表字元,值代表次數。
  • 遍歷字串得到每個字元。
  • 判斷Map中是否有該鍵。
  • 如果沒有,第一次出現,儲存次數為1;如果有,則說明已經出現過,獲取到對應的值進行++,再次儲存。
  • 列印最終結果

實現

方法介紹

public boolean containKey(Object key):判斷該集合中是否有此鍵。

程式碼:

public class Test {
    public static void main(String[] args) {
        /*
            Map集合練習:
                需求:輸入一個字串中每個字元出現次
         */
       // 分析:
       // 1.建立Map集合,限制鍵的型別為Character,值的型別為Integer
        Map<Character, Integer> map = new HashMap<>();

       // 2.建立Scanner物件
        Scanner sc = new Scanner(System.in);

       // 3.獲取鍵盤錄入的字串
        System.out.println("請輸入一個字串:");
        String str = sc.nextLine();

        // 4.遍歷字串的每一個字元
        for (int i = 0; i < str.length(); i++) {
           // 5.在迴圈中,獲取字串的字元,該字元作為map集合的鍵
            char cKey = str.charAt(i);

            // 6.在迴圈中,判斷遍歷出來的字元在map集合中是否存在該鍵
            boolean flag = map.containsKey(cKey);

            // 7.在迴圈中,如果不存在,字元作為鍵,值為1,儲存到map集合中
           // 8.在迴圈中,如果存在,獲取該字元鍵對應的值,進行+1後作為新的值
           //         然後在重新儲存到集合中
            if (flag == false){
                map.put(cKey,1);
            }else{
                Integer oldValue = map.get(cKey);// 獲取該字元鍵對應的值
                Integer newValue = oldValue + 1;// +1
                map.put(cKey,newValue);
            }
        }
       // 9.最後列印map集合
        System.out.println(map);
    }
}

第四章 集合的巢狀

  • 總述:任何集合內部都可以儲存其它任何集合

知識點--集合的巢狀

目標

  • 理解集合的巢狀

路徑

  • List巢狀List
  • List巢狀Map
  • Map巢狀Map

講解

List巢狀List

public class Test1 {
    public static void main(String[] args) {
        /*
            集合的巢狀:
                - List巢狀List
                - List巢狀Map
                - Map巢狀Map
            結論:任何集合內部都可以儲存其它任何集合
         */
        //  List巢狀List
        // 建立一個List集合,限制元素型別為String
        List<String> list1 = new ArrayList<>();

        // 往集合中新增元素
        list1.add("王寶強");
        list1.add("賈乃亮");
        list1.add("陳羽凡");

        // 建立一個List集合,限制元素型別為String
        List<String> list2 = new ArrayList<>();

        // 往集合中新增元素
        list2.add("馬蓉");
        list2.add("李小璐");
        list2.add("白百何");

        // 建立一個List集合,限制元素型別為List集合 (List集合中的元素是List集合)
        List<List<String>> list = new ArrayList<>();
        list.add(list1);
        list.add(list2);

        // 遍歷
        for (List<String> e : list) {
            for (String name : e) {
                System.out.println(name);
            }
            System.out.println("=============");
        }

        System.out.println(list);
    }
}


List巢狀Map

public class Test2 {
    public static void main(String[] args) {
        /*
            List巢狀Map:

         */
        // 建立Map集合物件
        Map<String,String> map1 = new HashMap<>();
        map1.put("it001","迪麗熱巴");
        map1.put("it002","古力娜扎");

        // 建立Map集合物件
        Map<String,String> map2 = new HashMap<>();
        map2.put("heima001","蔡徐坤");
        map2.put("heima002","李易峰");

        // 建立List集合,用來儲存以上2個map集合
        List<Map<String,String>> list = new ArrayList<>();
        list.add(map1);
        list.add(map2);

        System.out.println(list.size()); // 2

        for (Map<String, String> map : list) {
            // 遍歷獲取出來的map集合物件
            Set<String> keys = map.keySet();// 獲取map集合所有的鍵
            // 根據鍵找值
            for (String key : keys) {
                System.out.println(key + ","+ map.get(key));
            }
        }

    }
}

Map巢狀Map

public class Test3 {
    public static void main(String[] args) {
        /*
            Map巢狀Map:

         */
        // 建立Map集合物件
        Map<String,String> map1 = new HashMap<>();
        map1.put("it001","迪麗熱巴");
        map1.put("it002","古力娜扎");

        // 建立Map集合物件
        Map<String,String> map2 = new HashMap<>();
        map2.put("heima001","蔡徐坤");
        map2.put("heima002","李易峰");

        // 建立Map集合,把以上2個Map集合作為值儲存到這個map集合中
        Map<String, Map<String, String>> map = new HashMap<>();

        map.put("傳智部落格",map1);
        map.put("黑馬程式設計師",map2);

        System.out.println(map.size());// 2

        // 獲取map集合中的所有鍵
        Set<String> keys = map.keySet();
        // 遍歷所有的鍵
        for (String key : keys) {
            // 根據鍵找值
            Map<String, String> value = map.get(key);
            // 遍歷value這個Map集合
            Set<String> keySet = value.keySet();
            for (String k : keySet) {
                String v = value.get(k);
                System.out.println(k+","+v);
            }
        }
    }
}