Map常用的子类:
一、HashMap详解
1.特点
1)线程不安全。如果想要得到线程安全的HashMap,可以使用Collections的静态方法:Map map = Collections.synchronizedMap(new HashMap());
2)允许null键和null值。只能有一个键为null,可以有多个值为null。如果get()返回null,可以表示没有该键,也可以表示该键所对应的值为null。所以应该用containsKey()或containsValue()来判断是否存在。
3)时间复杂度是o(1)。
4)初始容量和装填因子影响其性能。
5)无序。即不能按照输入的顺序输出,而LinkedHashMap可以(双向链表对其进行保证)。
6)没有contains()方法
2.数据结构
public class HashMap<K,V> extends AbstractMap<K,V> implements Map<K,V>, Cloneable, Serializable
HashMap的底层是哈希数组,数组元素为Entry。HashMap通过key的hashCode来计算hash值,当hashCode相同时,通过“拉链法”解决冲突。当链表长度大于阈值(默认为8)时,将链表转化为红黑树,以减少搜索时间。原本Map.Entry接口的实现类Entry改名为了Node。转化为红黑树时改用另一种实现TreeNode。
Node类:
1 static class Node<K,V> implements Map.Entry<K,V> { 2 final int hash;//hash值 3 final K key; 4 V value; 5 Node<K,V> next;//指向下一个节点 6 7 Node(int hash, K key, V value, Node<K,V> next) { 8 this.hash = hash; 9 this.key = key; 10 this.value = value; 11 this.next = next; 12 } 13 14 public final K getKey() { return key; } 15 public final V getValue() { return value; } 16 public final String toString() { return key + "=" + value; } 17 //重写hashCode 18 public final int hashCode() { 19 return Objects.hashCode(key) ^ Objects.hashCode(value); 20 } 21 22 public final V setValue(V newValue) { 23 V oldValue = value; 24 value = newValue; 25 return oldValue; 26 } 27 //比较key和value是否equals相等 28 public final boolean equals(Object o) { 29 if (o == this) 30 return true; 31 if (o instanceof Map.Entry) { 32 Map.Entry<?,?> e = (Map.Entry<?,?>)o; 33 if (Objects.equals(key, e.getKey()) && 34 Objects.equals(value, e.getValue())) 35 return true; 36 } 37 return false; 38 } 39 }