jdk8版本Map接口
- Map和Collection并列存在,用于保存具有映射关系的数据:Key-Value
- Map中的Key和Value可以是任何引用类型的数据,会封装到HashMap$Node对象中
- Map中的Key不允许重复(与之前HashSet一样,底层源码中HashSet的元素就是HashMap的key)
- Map中的value可以重复
- Map的key可以为null,value也可以为null
- 常用类String可以作为key
- key和value存在单向一对一关系,指定的key可以找到对应的value
- 使用put压入两个相同的key时,后面的key对应的value会替换前面的
- HashMap线程不安全,无synchronized修饰
存储源码分析
- 底层的Node实现了Map.Entry接口(此处和上一节LinkedHashMap&Entry不同。后者是内部类,为HashMap.Node的子类)
//HashMap.java
static class Node<K,V> implements Map.Entry<K,V>{
final int hash;
final K key;
V value;
Node<K,V> next;
......
}
存储原理
- 底层上,一对key-value是存储在HashMap的Node中
HashMap$Node node = new Node(hash, key, value, null);
- 为了便于程序员遍历,还会创建EntrySet集合,该集合存放的元素类型:Entry
- 而一个Entry对象就有key-value:Set<Map.Entry<K,V>>entrySet;
- 在Entry中,让key指向Node中的key,value指向Node中的value(为了方便遍历)
- HashMap中有内部类:HashMap$EntrySet:
Set set = map.entrySet();
system.out.println(set.getClass());//HashMap$EntrySet
- entrySet中定义的类型是Map.Entry,但是实际上存放的还是HashMap$Node类型(只是实际位置不在这)(两者之间关系:Node实现了Map.Entry接口,当有一个类实现了接口,多态可以使用接口)
for(Object entry: set){
System.out.println(entry.getClass());//HashMap$Node
}
- Q:为什么这样便于遍历
- A:因为Map.Entry提供了重要方法:
- 1、getKey();
- 2、getValue();
- 遍历时用法:
for(Object obj:set){
Map.Entry entry = (Map.Entry) obj;//先向下转型
System.out.println(entry.getKey()+entry.getValue());
}
- 也可以使用map.KeySet(),将Key单独封装到一个Set; 或使用map.values(),将value单独封装到一个Collection中