Java集合-Map的應用

概述

Map集合是 雙列集合,使用Key-Value形式存儲數據。Map的特性是:Key的無序性、不重複性,Value的可重複性。
Map是泛型接口:

//K是Key的類型,V是Value的類型
public interface Map<K,V> {}

Entry

EntryMap接口中定義的內部泛型接口:

public interface Map<K,V> {
    ...
    interface Entry<K,V> {}
}

Entry是存儲單個Key-Value的數據類型。Map集合存儲的數據類型是Entry的實現類類型。Map集合按照EntryKey索引元素,EntryKey是無序,不重複的,因此Map集合的元素是無序的,不重複的

Map的存儲結構

Map使用Set集合存儲所有的Key,保證Key的不重複性,因此作爲Key的對象類必須重寫hashCode()equals()方法(TreeMap除外,TreeMap使用自然排序和定製排序保證Key的不重複性)。
Map使用Collection集合存儲所有的Value
Map使用Set集合存儲所有的Entry

Map中的常用方法

Map中的常用方法

public interface Map<K,V> {
    /* 添加Entry至Map集合,或修改已存在Entry的value. 
       添加不存在的key時,put()返回null;添加已存在的key時,
       對應的value將被新值覆蓋,put()返回被覆蓋之前的value. */
    /* 由於需要根據兩個key是否相等判斷key是否重複,
       充當key的對象類必須重寫hashCode()和equals(). */
    V put(K key,V value){}
    
    /* 添加另一個Map集合中的所有元素,已存在的Key對應的Value將被新值覆蓋。*/
    void putAll(Map<? extends K,?extends V> m){}
    
    /* 1.若Map集合中不存在該key,則添加key-value至Map集合。putIfAbsent()返回null.
       2.若Map集合中已存在該key但對應的value爲null,則將null覆蓋爲新的value值,
       putIfAbsent()返回null.
       3.若Map集合中已存在該key且對應的value不爲null,則不作任何改變。
       value不會被新值覆蓋,putIfAbsent()返回Map集合中該key對應的value. */
    V putIfAbsent(K key,V value){}
    
    /* 返回Map集合中key對應的value.集合中不存在該key則返回null. 
       有的Map集合能夠存放值爲null的key,此時使用containsKey()方法
       區分get()返回null是由於不存在該key,還是由於對應的value爲null.*/
    V get(Object key){}
    
    /* 判斷Map集合中是否存在該key. */
    boolean containsKey(Object key){}
    
    /* 判斷Map集合中是否存在該value. */
    boolean containsValue(Object value){}
    
    /* 從Map集合中移除指定key對應的Entry.
       若Map集合中不存在該key,remove()返回null;
       若Map集合中存在該key,remove()返回該key對應的value.
       有的Map集合能夠存放值爲null的key,此時使用containsKey()方法
       區分remove()返回null是由於不存在該key,還是由於對應的value爲null.*/
    V remove(Object key){}
    
    /* 若Map集合中存在該key,且對應的value恰好與指定value相等,
       則從Map集合中移除該Entry,remove()返回true.
       否則不作任何改變,remove()返回false. */
    /* 充當value的對象類必須重寫equals(). */
    default boolean remove(Object key,Object value){...}
    
    /* 清除Map集合中的所有Entry. */
    void clear(){}
    
    /* 將Map集合中key對應的value替換爲新值。
       若Map集合中存在該key,replace()返回替換之前的value.
       若Map集合中不存在該key,replace()返回null. 
       有的Map集合能夠存放值爲null的key,此時使用containsKey()方法
       區分replace()返回null是由於不存在該key,還是由於對應的value原值爲null.*/
    default V replace(K key,V value){}
    
    /* 若Map集合中存在該key,且對應的value恰好與指定的oldValue相等,
       則替換value爲newValue,replace()返回true.
       否則不作任何改變,replace()返回false. */
    default boolean replace(K key,V oldValue,V newValue){}
    
    /* 判斷Map集合中是否有元素。 */
    boolean isEmpty(){}
    
    /* 返回Map集合中的元素個數。 */
    int size(){}
    
    /* 獲得Map集合中key的Set集合,用於key的遍歷。 */
    Set<K> keySet(){}
    
    /* 獲得Map集合中value的Collection集合,用於value的遍歷。 */
    Collection<V> values(){}
    
    /* 獲得Map集合中Entry的Set集合,用於key-value的遍歷。 */
    Set<Map.Entry<K,V>> entrySet(){}
    
}

Map的遍歷

keySet()

@Test
public void test(){
    HashMap<String,Integer> map = new HashMap<>();
    map.put("BB",234);
    map.put("CC",345);
    map.put("AA",123);
    map.put("EE",567);
    map.put("DD",456);
    System.out.println(map);
    Set<String> set = map.keySet();
    Iterator<String> iterator = set.iterator();
    while(iterator.hasNext()){
        String key = iterator.next();
        Integer value = map.get(key);
        System.out.println(key+"->"+value);
    }
}

運行結果:

{BB=234, CC=345, AA=123, EE=567, DD=456}
BB->234
CC->345
AA->123
EE->567
DD->456

values()

@Test
public void test(){
    HashMap<String,Integer> map = new HashMap<>();
    map.put("BB",234);
    map.put("CC",345);
    map.put("AA",123);
    map.put("EE",567);
    map.put("DD",456);
    System.out.println(map);
    Collection<Integer> collection = map.values();
    Iterator<Integer> iterator = collection.iterator();
    while(iterator.hasNext()){
        System.out.print(iterator.next()+" ");
    }
}

運行結果:

{BB=234, CC=345, AA=123, EE=567, DD=456}
234 345 123 567 456 

entrySet()

@Test
public void test(){
    HashMap<String,Integer> map = new HashMap<>();
    map.put("BB",234);
    map.put("CC",345);
    map.put("AA",123);
    map.put("EE",567);
    map.put("DD",456);
    System.out.println(map);
    Set<Map.Entry<String,Integer>> set = map.entrySet();
    Iterator<Map.Entry<String,Integer>> iterator = set.iterator();
    while(iterator.hasNext()){
        Map.Entry<String,Integer> entry = iterator.next();
        String key = entry.getKey();
        Integer value = entry.getValue();
        System.out.println(key+"->"+value);
    }
}

HashMap

概述

HashMap線程不安全,執行效率高。HashMapKeyValue可以是null.
HashMap的底層結構是數組+鏈表+紅黑樹HashMap根據keyhashCode計算確定新添加元素在數組中的存放位置。同一個位置存放的多個元素通過鏈表或紅黑樹形式存儲。數組長度<64或同一位置存放的元素個數<8時,該位置的多個元素以鏈表形式存儲;數組長度>64時,在鏈表長度>8的位置,重新組織元素使之形成紅黑樹結構。
HashMap使用key哈希值通過某種算法確定元素的存儲位置,因此HashMap遍歷結果的元素順序不一定與元素的添加順序相同。

@Test
public void test(){
    HashMap<Integer,String> map = new HashMap<>();
    map.put(234,"BB");
    map.put(567,"EE");
    map.put(123,"AA");
    map.put(345,"CC");
    map.put(456,"DD");
    System.out.println(map);
    Set<Map.Entry<Integer,String>> set = map.entrySet();
    Iterator<Map.Entry<Integer,String>> iterator = set.iterator();
    while(iterator.hasNext()){
        Map.Entry<Integer,String> entry = iterator.next();
        Integer key = entry.getKey();
        String value = entry.getValue();
        System.out.println(key+"->"+value);
    }   
}

運行結果:

{567=EE, 456=DD, 345=CC, 234=BB, 123=AA}
567->EE
456->DD
345->CC
234->BB
123->AA

LinkedHashMap

LinkedHashMapHashMap的子類。LinkedHashMapHashMap的基礎上,在元素之間按照元素的添加順序設置雙向鏈表指針。LinkedHashMap的遍歷結果呈現出有序性,遍歷結果的元素順序與添加順序一致。
 對於需要頻繁遍歷的應用,LinkedHashMap的執行效率比HashMap更高。

@Test
public void test(){
    LinkedHashMap<Integer,String> map = new LinkedHashMap<>();
    map.put(234,"BB");
    map.put(567,"EE");
    map.put(123,"AA");
    map.put(345,"CC");
    map.put(456,"DD");
    System.out.println(map);
    Set<Map.Entry<Integer,String>> set = map.entrySet();
    Iterator<Map.Entry<Integer,String>> iterator = set.iterator();
    while(iterator.hasNext()){
        Map.Entry<Integer,String> entry = iterator.next();
        Integer key = entry.getKey();
        String value = entry.getValue();
        System.out.println(key+"->"+value);
    }   
}

運行結果:

{234=BB, 567=EE, 123=AA, 345=CC, 456=DD}
234->BB
567->EE
123->AA
345->CC
456->DD

TreeMap

概述

TreeMap用於需要對元素進行排序的應用。使用TreeMap()構造集合時,採用自然排序;使用TreeMap(Comparator<? super K> comparator)構造集合時,採用定製排序

TreeMap的自然排序

Person.java

public class Person implements Comparable<Person> {
    private String name;
    private int grade;
    public Person(String name,int grade){
        this.name = name;
        this.grade = grade;
    }
    public void setName(String name) {this.name = name;}
    public String getName() {return this.name;}
    public void setGrade(int grade) {this.grade = grade;}
    public int getGrade() {return this.grade;}
    
    @Override
    public int compareTo(Person p){
        if(Integer.compare(this.grade,p.grade) != 0) {
            //一級比較(從大到小排序)
            return -(Integer.compare(this.grade,p.grade));
        } else {
            //二級比較(從大到小排序)
            return -(this.name.compareTo(p.name));
        }
    }
    
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Person person = (Person) o;
        return grade == person.grade &&
                Objects.equals(name, person.name);
    }

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

Main.java

public class Main{
    public static void main(String[] args){
        TreeMap<Person,Integer> map = new TreeMap<>();
        map.put(new Person("Tony",100),40);
        map.put(new Person("Steve",90),35);
        map.put(new Person("Jerry",80),20);
        map.put(new Person("Thor",60),38);
        map.put(new Person("Peter",100),20);
        Set<Map.Entry<Person,Integer>> set = map.entrySet();
        Iterator<Map.Entry<Person,Integer>> iterator = set.iterator();
        while(iterator.hasNext()){
            Map.Entry<Person,Integer> entry = iterator.next();
            String name = entry.getKey().getName();
            int grade = entry.getKey().getGrade();
            int age = entry.getValue();
            System.out.println(name+" "+age+" : "+grade);
        }
    }
}

運行結果:

Tony 40 : 100
Peter 20 : 100
Steve 35 : 90
Jerry 20 : 80
Thor 38 : 60

TreeMap的定製排序

Person.java

public class Person {
    private String name;
    private int grade;
    public Person(String name,int grade){
        this.name = name;
        this.grade = grade;
    }
    public void setName(String name) {this.name = name;}
    public String getName() {return this.name;}
    public void setGrade(int grade) {this.grade = grade;}
    public int getGrade() {return this.grade;}
    
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Person person = (Person) o;
        return grade == person.grade &&
                Objects.equals(name, person.name);
    }

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

Main.java

public class Main{
    public static void main(String[] args){
        TreeMap<Person,Integer> map = new TreeMap<>(new Comparator<Person>(){
            @Override
            public int compare(Person p1,Person p2){
                if(Integer.compare(p1.getGrade(),p2.getGrade()) != 0){
                    //一級排序(從小到大)
                    return Integer.compare(p1.getGrade(),p2.getGrade());
                } else {
                    //二級排序(從小到大)
                    return p1.getName().compareTo(p2.getName());
                }
            }
        });
        map.put(new Person("Tony",100),40);
        map.put(new Person("Steve",90),35);
        map.put(new Person("Jerry",80),20);
        map.put(new Person("Thor",60),38);
        map.put(new Person("Peter",100),20);
        Set<Map.Entry<Person,Integer>> set = map.entrySet();
        Iterator<Map.Entry<Person,Integer>> iterator = set.iterator();
        while(iterator.hasNext()){
            Map.Entry<Person,Integer> entry = iterator.next();
            String name = entry.getKey().getName();
            int grade = entry.getKey().getGrade();
            int age = entry.getValue();
            System.out.println(name+" "+age+" : "+grade);
        }
    }
}

運行結果:

Thor 38 : 60
Jerry 20 : 80
Steve 35 : 90
Peter 20 : 100
Tony 40 : 100
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章