Map接口
① 映射(map)是一個存儲鍵/值對的對象。給定一個鍵,可以查詢到它的值,鍵和值都是對象;
② 鍵必須是唯一的,值可以重復;
③ 有些映射可以接收null鍵和null值,而有的不行;
④ 下面的接口可以支持映射:
接口
描述
Map
映射唯一關鍵字給值
Map.Entry
描述映射中的元素(關鍵字/值對)。這是Map的一個內部類
SortedMap
擴展Map以便關鍵字按升序保持
⑤ Map接口映射唯一鍵到值;
⑥ 鍵(key)是以後用於檢索值的對象。給定一個鍵和一個值,可以存儲這個值到Map對象中,以後可以使用對應鍵來檢索它;
⑦ Map接口定義的方法:
a) int size()
b) boolean isEmpty()
c) boolean containsKey(Object key)
d) boolean containsValue(Object value)
e) V get(Object key)
f) V put(K key,V value)
g) V remove(Object key)
h) Collection<V> values()
i) Set<Map.Entry<K,V>> entrySet() 返回包含映射關系的set視圖
⑧ Map.Entry接口代表映射項(鍵-值對)類型,是Map的嵌套類型;
⑨ Map接口定義的entrySet()方法返回包含映射項Entry的集合(Set),集合中的元素是Map.Entry類型;
⑩ Map.Entry接口定義的方法:
a) K getKey()
b) V getValue()
c) V setValue(V value)
HashMap及常用API
① HashMap類是基於哈希表的map接口的實現,並允許使用null鍵和null值;
② 構造方法:
a) HashMap()
b) HashMap(Map m)
c) HashMap(int capacity)
d) HashMap(int capacity,float fillRatio)
③ HashMap實現Map並擴展AbstractMap,本身並沒有增加任何新的方法;
④ 散列映射不保證它的元素的順序,元素加入散列映射的順序並不一定是它們被迭代讀出的順序;
添加及輸出
Map<String, String> map = new HashMap<String, String>(); map.put("zhangsan", "張三"); map.put("zhangsan", "李四");//會覆蓋上面的'張三'值 map.put("jay", "小明"); map.put("marry", "小紅"); System.out.println(map);
輸出結果:
{jay=小明, zhangsan=李四, marry=小紅}
獲取map中的所有鍵
Set<String> keys=map.keySet(); for(String key:keys){ System.out.println(key); }
輸出結果:
jay
zhangsan
marry
獲取map中的所有值
Collection<String> values=map.values(); for(String value:values){ System.out.println(value); }
輸出結果:
小明
李四
小紅
得到key的同時得到key所對應的值
Set<String> keys=map.keySet(); for(String key:keys){ System.out.println(key+"--"+map.get(key)); }
輸出結果:
jay--小明
zhangsan--李四
marry--小紅
System.out.println(map.size());// 返回此映射中的鍵-值映射關系數 System.out.println(map.isEmpty());// 如果此映射不包含鍵-值映射關系,則返回 true
輸出結果:
3
false
返回此映射所包含的映射關系的 Set
視圖
//當我們調用put(key,value)方法時,首先會把key和value封裝到 //Entry這個靜態內部類對象中,把Entry對象再添加到數組中, //所以我們想獲取map中的所有鍵值對時,我們只要獲取數組中的所有Entry對象 //接下來調用Entry對象中的getKey和getValue方法就能獲得鍵值對 Set<Entry<String, String>> entrys= map.entrySet(); for(Entry<String,String> entry:entrys){ System.out.println(entry.getKey()+"----"+entry.getValue()); }
輸出結果:
jay----小明
zhangsan----李四
marry----小紅
put方法步驟解析
/* * put方法步驟解析 * HashMap調用默認構造方法會產生一個底層長度為16的Entry數組 * int hash=hash(key.hashCode()); * 首先調用key的hashCode方法來得到一個整數--哈希碼 * 把哈希碼作為參數傳到hash函數中進行運算--散列運算--得到一個整型--散列值 * int i=indexFor(hash,table.length) * 把散列值和數組的長度來進行運算,最終得到存放到數組的位置(i) * * HashMap內部的結構是數組鏈表結構 * 因為不同的key有可能算出來的事相同的散列值,根據散列值計算出存放 * 到數組的下標會沖突 * */
int i=hash(zhang.hashCode());
int j=hash(li.hashCode());
i可能與j相同,假如都為4,則 zhan—‘張三’ 存放在4的位置上,
li—‘李四’ 存放在4的位置上
get方法解析
/* * get方法解析 * 使用關鍵字查找時,可能會在同一個散列值位置下有多個key-value, * 多個key-value以鏈表的形式存放,再一個一個比較,直到找到為止 * 若找不到返回null * */
哈希碼的產生和使用
① 當調用對象的hashCode()方法時就會返回當前對象的哈希碼值。支持此方法是為了提高哈希表的性能;
② hashCode的常協議:
a) 在Java應用程序執行期間,在對同一對象多次調用hashCode方法時,必須一致地返回相同的整數,前提是將對象進行equals比較時所用的信息沒有被修改,從某一應用程序的一次執行到同一應用程序的另一次執行該整數無需保持一致;
b) 如果根據equals(Object) 方法,兩個對象是相等的,那麼對這兩個對象中的每個對象調用hashCode方法都必須生成相同的整數結果;
注:這裡說的equals(Object)方法是指Object類中未被子類重寫過的equals方法;
c) 如果根據equals(java.lang.Object)方法,兩個對象不相等,那麼對這兩個對象中的任一對象上調用hashCode方法不要求一定生成不同的整數結果。但是,我們應該意識到,為不相等的對象生成不同的整數結果可以提高哈希表的性能;
創建一個Student 類
class Student{ private String name; private int age; public Student(String name, int age) { super(); this.name = name; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } }
在主方法中創建對象,賦值,查看元素
Map<Student,String> map=new HashMap<Student, String>(); map.put(new Student("zhang",20), "張三"); map.put(new Student("li",30), "李四"); map.put(new Student("wang",20), "王五"); map.put(new Student("li",30), "小明"); System.out.println(map); System.out.println(map.size());
輸出結果:
{com.iotek.map.Student@7852e922=小明, com.iotek.map.Student@2a139a55=張三, com.iotek.map.Student@15db9742=李四, com.iotek.map.Student@6d06d69c=王五}
4
此處放入2個new Student("li",30)相同的鍵,被看作是2個
若要當做1個則要重寫hashCode 方法與equals方法,(可生成)。
@Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + age; 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; Student other = (Student) obj; if (age != other.age) return false; if (name == null) { if (other.name != null) return false; } else if (!name.equals(other.name)) return false; return true; }
再次執行,輸出結果:
{com.iotek.map.Student@14e0=小明, com.iotek.map.Student@379830=王五, com.iotek.map.Student@6e7fa19=張三}
3