文章目錄
概述
Map
集合是 雙列集合,使用Key-Value
形式存儲數據。Map
的特性是:Key
的無序性、不重複性,Value
的可重複性。
Map
是泛型接口:
//K是Key的類型,V是Value的類型
public interface Map<K,V> {}
Entry
Entry
是Map
接口中定義的內部泛型接口:
public interface Map<K,V> {
...
interface Entry<K,V> {}
}
Entry
是存儲單個Key-Value
的數據類型。Map
集合存儲的數據類型是Entry
的實現類類型。Map
集合按照Entry
的Key
索引元素,Entry
的Key
是無序,不重複的,因此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
線程不安全,執行效率高。HashMap
的Key
和Value
可以是null
.
HashMap
的底層結構是數組+鏈表+紅黑樹。HashMap
根據key
的hashCode
計算確定新添加元素在數組中的存放位置。同一個位置存放的多個元素通過鏈表或紅黑樹形式存儲。數組長度<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
LinkedHashMap
是HashMap
的子類。LinkedHashMap
在HashMap
的基礎上,在元素之間按照元素的添加順序設置雙向鏈表指針。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