隨筆1 interface Map


第一次寫筆記就從map開始吧,如上圖所示,綠色的是interface,黃色的是abstract class,藍色的是class,可以看出所有和圖相關的接口,抽象類和類的起源都是interface map<K,V>。現在看一下當前Map接口中實現了什么,里面包含了一個內部接口interface Entry<K,V>,聲明了14個方法,同時還定義了11個方法(在jdk1.8中,在interface中可以使用default關鍵字來定義完整的方法)

由於聲明的方法都是原來版本jdk已經存在的,比較簡單,所以我們從聲明的方法開始介紹

  1 public interface Map<K, V> {
  2 
  3     /**
  4      * 方法返回鍵值對個數,當鍵值對個數大於Integer.MAX_VALUE
  5      * 時返回Integer.MAX_VALUE
  6      */
  7     int size();
  8     
  9     /**
 10      * 當Map中沒有鍵值對的時候,返回true
 11      */
 12     boolean isEmpty();
 13     
 14     /**
 15      * 當Map中的鍵包含key的時候返回true,相當於執行了如下語句
 16      * key==null ? k==null : key.equals(k)
 17      * 此處應該注意Map中的鍵是可以為null的,但是只可以有一個
 18      * 需要注意的是本方法會有兩個異常
 19      * ClassCastException當傳入的key和本Map中設置的key類型不相容的時候
 20      * NullPointerException當傳入的key==null,並且Map中的鍵沒有null的時候
 21      */
 22     boolean containsKey(Object key);
 23     
 24     /**
 25      * 當有多於一個key的value等於傳入的value時會返回true
 26      * 相當於執行value==null ? v==null : value.equals(v)
 27      * 可見value也是可以為null的
 28      * 需要注意的是本方法會拋出兩個異常
 29      * ClassCastException當傳入的值和Map中的值不相容的時候
 30      * NullPointerException當value中沒有一個值為null的時候
 31      */
 32     boolean containsValue(Object value);
 33     
 34     /**
 35      * 如果當前的key存在於Map中,會返回對應的value,否則會返回null
 36      * 需要注意的是本方法會有兩個異常
 37      * ClassCastException當傳入的key和本Map中設置的key類型不相容的時候
 38      * NullPointerException當傳入的key==null,並且Map中的鍵沒有null的時候
 39      * 
 40      */
 41     V get(Object key);
 42     
 43     /**
 44      * 當key不存在是會放入新的鍵值對,當key存在時,會更新key對應的value值
 45      * 本方法會產生四個異常
 46      * UnsupportedOperationException當Map不支持put操作的時候
 47      * ClassCastException當key或者value不相容的時候
 48      * NullPointerException當Map不允許key或者value為null的時候
 49      * IllegalArgumentException如果指定鍵或值的某些屬性阻止將其存儲在此映射中
 50      */
 51     V put(K key, V value);
 52     
 53     /**
 54      * 當Map中有這個key的時候,會返回相應的value,否則會返回null
 55      * 本方法會拋出三個異常
 56      * UnsupportedOperationException當Map不支持此操作時
 57      * ClassCastException當key的類型不相容時
 58      * NullPointerException當key是null並且這個Map不允許key為null時
 59      */
 60     V remove(Object key);
 61     
 62     /**
 63      * 將一個Map的所有鍵值對放入本Map,對於每一個鍵值對都調用的是put(K key, V value)方法
 64      * 本方法會產生四個異常
 65      * UnsupportedOperationException當Map不支持put操作的時候
 66      * ClassCastException當key或者value不相容的時候
 67      * NullPointerException當Map不允許key或者value為null的時候
 68      * IllegalArgumentException如果指定鍵或值的某些屬性阻止將其存儲在此映射中
 69      */
 70     void putAll(Map<? extends K, ? extends V> m);
 71     
 72     /**
 73      * 從Map中移除所有的元素
 74      * 會拋出一個異常
 75      * UnsupportedOperationException當Map不支持本操作的時候
 76      */
 77     void clear();
 78     
 79     /**
 80      * 會以集合的形式返回key,當修改Map的key時會反應在Set中,反之亦然
 81      */
 82     Set<K> keySet();
 83     
 84     /**
 85      * 返回一個Collection集合對於值來說,因為值可以有重復的,所以才選用了Collection
 86      * 同樣的對Map修改時,也會反應到Collection上
 87      */
 88     Collection<V> values();
 89     
 90     /**
 91      * 返回一個鍵值對的集合Entry<K, V>
 92      */
 93     Set<Map.Entry<K, V>> entrySet();
 94     
 95     /**
 96      * 本方法是用來比較兩個Map是否相同的
 97      */
 98     boolean equals(Object o);
 99     
100     /**
101      * 本方法是用於返回一個Map的Hash值,本方法要求對Map中的每一個Entry<K,V>進行運算的
102      * 這樣保證了當m1.equals(m2)時m1.hashCode()==m2.hashCode()
103      */
104     int hashCode();
105     
106     
107 }

 

接下來我們來看一下內部的接口interface Entry<K,V>的內容

 1 interface Entry<K,V> {
 2         /**
 3          * 返回Entry的key
 4          * IllegalStateException 並不要求實現類必須拋出這個異常,在訪問Map中的Entry元素時可能用到,即Entry已經被移除時
 5          */
 6         K getKey();
 7         
 8         /**
 9          * 返回Entry的value
10          * IllegalStateException 並不要求實現類必須拋出這個異常,在訪問Map中的Entry元素時可能用到,即Entry已經被移除時
11          */
12         V getValue();
13         
14         /**
15          * 重新設置Entry的value,但是當映射關系被移除時,該方法的行為還未被定義
16          * 拋出五個異常
17          * UnsupportedOperationException如果Map不支持put操作
18          * ClassCastException當與指定類型不相容的時候
19          * NullPointerException當Map不允許出現null而此時設置的值為null的時候
20          * IllegalArgumentException如果當前值的屬性不允許它存儲在圖中
21          * IllegalStateException並不要求實現類必須拋出這個異常,在訪問Map中的Entry元素時可能用到,即Entry已經被移除時
22          */
23         V setValue(V value);
24         
25         /**
26          * 當比較對象也是一個Entry並且表達同樣的映射關系的時候返回true
27          */
28         boolean equals(Object o);
29         
30         /**
31          * 本方法實現的要求是當e1.equals(e2)時,e1.hashCode()==e2.hashCode()
32          */
33         int hashCode();
34         
35         //從以下開始都是jdk1.8新增的方法,對於jdk1.8的新特性就不再這里分析了,會單寫一篇的
36         /**
37          * 本方法會返回一個比較器,用來實現對Entry的key進行比較
38          */
39         public static <K extends Comparable<? super K>, V> Comparator<Map.Entry<K,V>> comparingByKey() {
40             return (Comparator<Map.Entry<K, V>> & Serializable)
41                 (c1, c2) -> c1.getKey().compareTo(c2.getKey());
42         }
43         
44         /**
45          * 本方法返回一個比較器,用來實現對Entry的value進行比較,這里表示返回值同時滿足兩個接口
46          */
47         public static <K, V extends Comparable<? super V>> Comparator<Map.Entry<K,V>> comparingByValue() {
48             return (Comparator<Map.Entry<K, V>> & Serializable)
49                 (c1, c2) -> c1.getValue().compareTo(c2.getValue());
50         }
51         
52         /**
53          * 這個方法和上兩個方法不同之處在於上兩個要求K或者V實現Comparable接口,使得本身可以比較
54          * 而這個方法中並沒有對K,V有什么要求,而是需要一個已經實現Comparator的接口
55          */
56         public static <K, V> Comparator<Map.Entry<K, V>> comparingByKey(Comparator<? super K> cmp) {
57             Objects.requireNonNull(cmp);
58             return (Comparator<Map.Entry<K, V>> & Serializable)
59                 (c1, c2) -> cmp.compare(c1.getKey(), c2.getKey());
60         }
61         
62         /**
63          * 同上
64          */
65         public static <K, V> Comparator<Map.Entry<K, V>> comparingByValue(Comparator<? super V> cmp) {
66             Objects.requireNonNull(cmp);
67             return (Comparator<Map.Entry<K, V>> & Serializable)
68                 (c1, c2) -> cmp.compare(c1.getValue(), c2.getValue());
69         }
70         
71     }

這里簡單解釋一下上述代碼中jdk1.8的新特性以便使代碼容易理解一些,Comparator<Map.Entry<K, V>> & Serializable這里並不是表達與操作,而是返回值同時實現了這兩個接口,(c1, c2) -> cmp.compare(c1.getValue(), c2.getValue())是lambda表達式實現了一個函數式接口Comparator的compare方法

最后一部分是Map在jdk1.8中新增的default方法,在jdk1.8中,可以在interface中實現方法了,但是得用default關鍵字修飾

  1     /**
  2      * 本方法是在普通get方法上增加了一個默認值,防止了得到的value為null的情況
  3      * 拋出兩個異常
  4      * ClassCastException當key和Map中要求的key不兼容時
  5      * NullPointerException當Map不支持null為key時
  6      */
  7     default V getOrDefault(Object key, V defaultValue) {
  8         V v;
  9         return (((v = get(key)) != null) || containsKey(key))
 10             ? v
 11             : defaultValue;
 12     }
 13     
 14     /**
 15      * 對Map中的每一個Entry進行一次action包含的操作
 16      * 拋出兩個異常
 17      * NullPointerException當action為null時
 18      * ConcurrentModificationException在迭代過程中有元素被移除
 19      */
 20     default void forEach(BiConsumer<? super K, ? super V> action) {
 21         Objects.requireNonNull(action);
 22         for (Map.Entry<K, V> entry : entrySet()) {
 23             K k;
 24             V v;
 25             try {
 26                 k = entry.getKey();
 27                 v = entry.getValue();
 28             } catch(IllegalStateException ise) {
 29                 // this usually means the entry is no longer in the map.
 30                 throw new ConcurrentModificationException(ise);
 31             }
 32             action.accept(k, v);
 33         }
 34     }
 35     
 36     /**
 37      * 對Map中的每個Entry都用function進行操作,返回得到的結果重新設置value
 38      */
 39     default void replaceAll(BiFunction<? super K, ? super V, ? extends V> function) {
 40         Objects.requireNonNull(function);
 41         for (Map.Entry<K, V> entry : entrySet()) {
 42             K k;
 43             V v;
 44             try {
 45                 k = entry.getKey();
 46                 v = entry.getValue();
 47             } catch(IllegalStateException ise) {
 48                 // this usually means the entry is no longer in the map.
 49                 throw new ConcurrentModificationException(ise);
 50             }
 51 
 52             // ise thrown from function is not a cme.
 53             v = function.apply(k, v);
 54 
 55             try {
 56                 entry.setValue(v);
 57             } catch(IllegalStateException ise) {
 58                 // this usually means the entry is no longer in the map.
 59                 throw new ConcurrentModificationException(ise);
 60             }
 61         }
 62     }
 63     
 64     /**
 65      * 當key對應的value為null的時候,設置新的value值
 66      */
 67     default V putIfAbsent(K key, V value) {
 68         V v = get(key);
 69         if (v == null) {
 70             v = put(key, value);
 71         }
 72 
 73         return v;
 74     }
 75     
 76     /**
 77      * 當key和value與當前map中有完全相同的,就刪除該元素,返回true,否則返回false,不做任何操作
 78      */
 79     default boolean remove(Object key, Object value) {
 80         Object curValue = get(key);
 81         if (!Objects.equals(curValue, value) ||
 82             (curValue == null && !containsKey(key))) {
 83             return false;
 84         }
 85         remove(key);
 86         return true;
 87     }
 88     
 89     /**
 90      * 當Map中存在key->oldValue時,替換為key->newValue,返回true,否則返回false,不做任何操作
 91      */
 92     default boolean replace(K key, V oldValue, V newValue) {
 93         Object curValue = get(key);
 94         if (!Objects.equals(curValue, oldValue) ||
 95             (curValue == null && !containsKey(key))) {
 96             return false;
 97         }
 98         put(key, newValue);
 99         return true;
100     }
101     
102     /**
103      * 用新的value替換老的value,並返回老的value,如果key不存在,返回null
104      */
105     default V replace(K key, V value) {
106         V curValue;
107         if (((curValue = get(key)) != null) || containsKey(key)) {
108             curValue = put(key, value);
109         }
110         return curValue;
111     }
112     
113     /**
114      * 傳入一個單參數函數,找到key對應的value,如果value==null,然后對key進行重新計算,得到新的value,返回新的value。否則返回null
115      */
116     default V computeIfAbsent(K key,
117             Function<? super K, ? extends V> mappingFunction) {
118         Objects.requireNonNull(mappingFunction);
119         V v;
120         if ((v = get(key)) == null) {
121             V newValue;
122             if ((newValue = mappingFunction.apply(key)) != null) {
123                 put(key, newValue);
124                 return newValue;
125             }
126         }
127 
128         return v;
129     }
130     
131     /**
132      * 如果Map中存在key,並且對應的value!=null的時候,用傳入的兩個參數的函數進行重新計算,得到新的value,如果新的value==null
133      * 就刪除這個鍵值對,返回null,否則覆蓋舊值,返回新的value,如果key不存在,也返回null
134      */
135     default V computeIfPresent(K key,
136             BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
137         Objects.requireNonNull(remappingFunction);
138         V oldValue;
139         if ((oldValue = get(key)) != null) {
140             V newValue = remappingFunction.apply(key, oldValue);
141             if (newValue != null) {
142                 put(key, newValue);
143                 return newValue;
144             } else {
145                 remove(key);
146                 return null;
147             }
148         } else {
149             return null;
150         }
151     }
152     
153     /**
154      * 通過原來的鍵值對,計算出一個新的值,如果新的值不為空,重新設置鍵值對,並返回新的value,否則刪除原來的鍵值對,返回null
155      */
156     default V compute(K key,
157             BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
158         Objects.requireNonNull(remappingFunction);
159         V oldValue = get(key);
160 
161         V newValue = remappingFunction.apply(key, oldValue);
162         if (newValue == null) {
163             // delete mapping
164             if (oldValue != null || containsKey(key)) {
165                 // something to remove
166                 remove(key);
167                 return null;
168             } else {
169                 // nothing to do. Leave things as they were.
170                 return null;
171             }
172         } else {
173             // add or replace old mapping
174             put(key, newValue);
175             return newValue;
176         }
177     }
178     
179     /**
180      * 將舊的value和新的value進行混合計算,得到另一個value,如果這個value不為空,就和原來的key形成映射關系,返回新的value,
181      * 否則移除原來的鍵值對,返回null
182      */
183     default V merge(K key, V value,
184             BiFunction<? super V, ? super V, ? extends V> remappingFunction) {
185         Objects.requireNonNull(remappingFunction);
186         Objects.requireNonNull(value);
187         V oldValue = get(key);
188         V newValue = (oldValue == null) ? value :
189                    remappingFunction.apply(oldValue, value);
190         if(newValue == null) {
191             remove(key);
192         } else {
193             put(key, newValue);
194         }
195         return newValue;
196     }

這些方法中出現了比較陌生的BiConsumer,BiFunction和Function這三個接口,都是在java.util.function包下的新接口,可以把他們看做一個函數去理解就好了。BiConsumer

是接受兩個參數,沒有計算的返回值。BiFunction是接受兩個參數返回一個參數。Function是接受一個參數返回一個參數。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM