1. 程式人生 > 其它 >四十、Map集合

四十、Map集合

1、概述

java.util.Map<K,V> 集合,裡面儲存的資料是成對存在的,稱之為雙列集合。儲存的資料,我們稱為鍵值對。 之前所學的Collection集合中元素單個單個存在的,稱為單列集合。

K:鍵的資料型別;V:值的資料型別

  1. 鍵不能重複,值可以重複
  2. 鍵和值是一一對應的,通過鍵可以找到對應的值
  3. (鍵 + 值)一起是一個整體,我們稱之為 “鍵值對” 或者 “鍵值對物件” ,在Java中叫做 “Entry物件”

2、Map實現類

HashMap:

此前的HashSet底層實現就是HashMap完成的,HashSet儲存的元素其實就是HashMap集合中儲存的鍵,底層結構是雜湊表結構,具有鍵唯一,無序,特點。

LinkedHashMap:

底層結構是有連結串列和雜湊表結構,去重,有序

TreeMap:

底層是有紅黑樹,去重,通過鍵進行排序

3、Map中常用方法

方法 描述
public V put(K key, V value) 把指定的鍵與指定的值新增到Map集合中。也可以做修改操作
public V remove(Object key) 把指定的鍵 所對應的鍵值對元素 在Map集合中刪除,返回被刪除元素的值。
public V get(Object key) 根據指定的鍵,在Map集合中獲取對應的值。
public Set<K> keySet() 獲取Map集合中所有的鍵,儲存到 Set 集合中。
Collection<V> values() 獲取Map集合中所有的值,儲存到 Collection 集合中。
public Set<Map.Entry<K,V>> entrySet() 獲取到Map集合中所有的鍵值對物件的集合(Set集合)。
public boolean containKey(Object key) 判斷該集合中是否有此 key 鍵。
public boolean containValue(Object value) 判斷該集合中是否有此 value 值。

4、Map集合遍歷

Map集合既不能使用索引來遍歷,也不能使用迭代器遍歷,如果要進行對Map集合遍歷,可以有兩種方式:

  • 獲取健集合 , 拿到每一個鍵 , 在通過鍵找到對應值

  • 獲取鍵值對物件集合,拿到每一個鍵值對物件 , 在獲取鍵和值

遍歷一:鍵找值方式

操作步驟:

  1. 獲取Map中所有的鍵,由於鍵是唯一的,所以返回一個Set集合儲存所有的鍵。方法提示:keyset()
  2. 遍歷鍵的Set集合,得到每一個鍵。
  3. 根據鍵,獲取鍵所對應的值。方法提示:get(K key)

遍歷圖解:

遍歷二:鍵值對物件遍歷

即通過集合中每個鍵值對(Entry)物件,獲取鍵值對(Entry)物件中的鍵與值

操作步驟:

  1. 獲取Map結合中,所有的鍵值對(Entry)物件,以Set集合形式返回。使用方法entrySet()

    public Set<Map.Entry<K,V>> entrySet()

  2. 遍歷包含鍵值對(Entry)物件的Set集合,得到每一個鍵值對(Entry)物件

  3. 通過鍵值對(Entry)物件,獲取Entry物件中的鍵與值。使用方法getKey() getValue()

    public K getKey()

    public V getValue()

遍歷圖解:

tips:Map集合不能直接使用迭代器或者foreach進行遍歷。但是轉成Set之後就可以使用了。

5、HashMap儲存自定義型別

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

【學生類】
public class Student {
    private String name;
    private int age;

    //構造方法
    //get/set
    @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 HashMapTest {
    public static void main(String[] args) {
        //1,建立Hashmap集合物件。
        Map<Student,String> map = new HashMap<Student,String>();
        //2,新增元素。
        map.put(new Student("lisi",28), "上海");
        map.put(new Student("wangwu",22), "北京");
        map.put(new Student("wangwu",22), "南京");
        
        //3,取出元素。鍵找值方式
        Set<Student> keySet = map.keySet();
        for(Student key: keySet){
            String value = map.get(key);
            System.out.println(key.toString()+"....."+value);
        }
    }
} 
  • 當給HashMap中存放自定義物件時,如果自定義物件作為key存在,這時要保證物件唯一,必須複寫物件的hashCode和equals方法(如果忘記,請回顧HashSet存放自定義物件)。
  • 如果要保證map中存放的key和取出的順序一致,可以使用java.util.LinkedHashMap集合來存放。

6、LinkedHashMap

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

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

程式碼體現:

public class LinkedHashMapDemo {
    public static void main(String[] args) {
        LinkedHashMap<String, String> map = new LinkedHashMap<String, String>();
        map.put("鄧超", "孫儷");
        map.put("李晨", "范冰冰");
        map.put("劉德華", "朱麗倩");
        Set<Entry<String, String>> entrySet = map.entrySet();
        for (Entry<String, String> entry : entrySet) {
            System.out.println(entry.getKey() + "  " + entry.getValue());
        }
    }
}
/*
鄧超  孫儷
李晨  范冰冰
劉德華  朱麗倩
*/

7、TreeMap集合

7.1 概述

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

public TreeMap():預設使用自然排序
public TreeMap(Comparator<? super K> comparator) Comparator比較器排序

7.2 自然排序

public static void main(String[] args) {
 	TreeMap<Integer, String> map = new TreeMap<Integer, String>();
  	map.put(1,"張三");
  	map.put(4,"趙六");
  	map.put(3,"王五");
  	map.put(6,"酒八");
  	map.put(5,"老七");
  	map.put(2,"李四");
  	System.out.println(map);
}

控制檯的輸出結果為:
{1=張三, 2=李四, 3=王五, 4=趙六, 5=老七, 6=酒八}

7.3 比較器排序

需求:

  1. 建立一個TreeMap集合,鍵是學生物件(Student),值是居住地 (String)。儲存多個元素,並遍歷。
  2. 要求按照學生的年齡進行升序排序,如果年齡相同,比較姓名的首字母升序, 如果年齡和姓名都是相同,認為是同一個元素;

實現:

為了保證age和name相同的物件是同一個,Student類必須重寫hashCode和equals方法

【Student類】
public class Student {
    private int age;
    private String name;
	//省略get/set..
    public Student() {}
    public Student(int age, String name) {
        this.age = age;
        this.name = name;
    }
    @Override
    public String toString() {
        return "Student{" +
                "age=" + age +
                ", name='" + name + '\'' +
                '}';
    }
    @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(age, name);
    }
}

【測試類】
public static void main(String[] args) {
  	TreeMap<Student, String> map = new TreeMap<Student, String>(new Comparator<Student>() {
    	@Override
    	public int compare(Student o1, Student o2) {
      		//先按照年齡升序
      		int result = o1.getAge() - o2.getAge();
      		if (result == 0) {
        		//年齡相同,則按照名字的首字母升序
        		return o1.getName().charAt(0) - o2.getName().charAt(0);
      		} else {
        		//年齡不同,直接返回結果
        		return result;
      		}
    	}
  	});
  	map.put(new Student(30, "jack"), "深圳");
  	map.put(new Student(10, "rose"), "北京");
  	map.put(new Student(20, "tom"), "上海");
  	map.put(new Student(10, "marry"), "南京");
  	map.put(new Student(30, "lucy"), "廣州");
  	System.out.println(map);
}
/*
控制檯的輸出結果為:
{
  Student{age=10, name='marry'}=南京, 
  Student{age=10, name='rose'}=北京, 
  Student{age=20, name='tom'}=上海, 
  Student{age=30, name='jack'}=深圳, 
  Student{age=30, name='lucy'}=廣州
} 
*/