null作为键放进HashMap, LinkedHashMap

  1. Map: key不可重复,value可以
  2. HashMap, LinkedHashMap都可以多个null作为key, TreeMap不能null作为key
  3. HashMap, LinkedHashMap: put进去KV对的时候,重复的key最终对应的value是最后那个value
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public static Map putSome(Map<String, String> map) {
map.put("gender", "male");
map.put("name", "lei");
map.put("from", "Asia");
map.put("name", "kawasaki");
map.put("name", "yamamoto");
map.put(null, null);
map.put(null, null);
map.put(null, "null-later-v2");
return map;
}

public static void main(String[] args) {
// HashMap, LinkedHashMap都可以多个null作为key
System.out.println(putSome(new HashMap<String, String>()));
// TreeMap不允许null作为key
// System.out.println(putSome(new TreeMap<String, String>()));
System.out.println(putSome(new LinkedHashMap<String, String>()));
}
1
2
{null=null-later-v2, gender=male, name=yamamoto, from=Asia}
{gender=male, name=yamamoto, from=Asia, null=null-later-v2}

HashMap和LinkedHashMap的区别

Linked: 内部维持了一个双向链表,map中的键值对保持是插入的顺序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
System.out.println("*************************LinkedHashMap*************");
Map<Integer,String> map = new LinkedHashMap<Integer,String>();
map.put(6, "apple");
map.put(3, "banana");
map.put(2,"pear");

for (Iterator it = map.keySet().iterator();it.hasNext();)
{
Object key = it.next();
System.out.println( key+"="+ map.get(key));
}

System.out.println("*************************HashMap*************");
Map<Integer,String> map1 = new HashMap<Integer,String>();
map1.put(6, "apple");
map1.put(3, "banana");
map1.put(2,"pear");

for (Iterator it = map1.keySet().iterator();it.hasNext();)
{
Object key = it.next();
System.out.println( key+"="+ map1.get(key));
}
}
1
2
3
4
5
6
7
8
*************************LinkedHashMap*************
6=apple
3=banana
2=pear
*************************HashMap**************************
2=pear
6=apple
3=banana

i.e. LinkedHashMap的特点是put进去的对象位置没有发生变化,而HashMap会发生变化

分别介绍 HashMap, LinkedHashMap, TreeMap

HashMap

  1. 访问速度快,遍历取得数据顺序随机。
  2. HashMap不支持线程同步, i.e. 任意时刻可能有多个线程同时写HashMap, 可能导致数据不一致。
  3. 如果需要同步,可以用ConcurrentHashMap, 或者CollectionssynchronizedMap.
  4. 初始化默认大小是16,而且是成倍增长。
    1
    2
    3
    4
    5
    6
    7
    /**
    * Constructs an empty <tt>HashMap</tt> with the default initial capacity
    * (16) and the default load factor (0.75).
    */
    public HashMap() {
    this(DEFAULT_INITIAL_CAPACITY, DEFAULT_LOAD_FACTOR);
    }
1
2
3
4
5
6
7
8
9
void addEntry(int hash, K key, V value, int bucketIndex) {
if ((size >= threshold) && (null != table[bucketIndex])) {
resize(2 * table.length);
hash = (null != key) ? hash(key) : 0;
bucketIndex = indexFor(hash, table.length);
}

createEntry(hash, key, value, bucketIndex);
}

LinkedHashMap

  1. 保存了纪录的插入顺序,在用Iterator遍历LinkedHashMap时,先得到的纪录就是先插入的。
  2. 遍历时因为是linkedlist vs array, 所以比HashMap慢
  3. 但是有一种例外: 当HashMap容量很大,实际数据较少时,HashMap遍历可能比LinkedHashMap慢;这是因为LinkedHashMap的遍历速度只和实际数据有关,和容量无关,而HashMap的遍历速度和容量有关。

TreeMap

  1. 实现了SortMap接口,能够把保存的纪录根据key排序,默认按照key升序排序
  2. 可以指定排序比较器,用Iterator遍历TreeMap时,得到的纪录是排序过的

总结

  1. 只是一般的插入,删除,定位元素,HashMap用的最多
  2. 按自然顺序或者自定义顺序遍历key:TreeMap
  3. 输出顺序和输入顺序相同: LinkedHashMap