文章目录
概述
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