一、Map是什么?
Map用于保存具有映射关系的数据,Map集合里保存着两组值,一组用于保存Map的key–键,另一组保存着Map的value—值
1.Map的特点
- 通常情况下一个key对应一个value
- 一个key可以对应两个value 但是对应后值会被覆盖
- 多个key可以对应一个值
- Map没有index,也没有实现迭代器接口
2.Map中常用的方法
void clear()
:删除该Map对象中所有键值对;boolean containsKey(Object key)
:查询Map中是否包含指定的key值;boolean containsValue(Object value)
:查询Map中是否包含一个或多个value;Set entrySet()
:返回map中包含的键值对所组成的Set集合,每个集合都是Map.Entry对象。Object get()
:返回指定key对应的value,如果不包含key则返回null;boolean isEmpty()
:查询该Map是否为空;Set keySet()
:返回Map中所有key组成的集合;Collection values()
:返回该Map里所有value组成的Collection。Object put(Object key,Object value)
:添加一个键值对,如果集合中的key重复,则覆盖原来的键值对;void putAll(Map m)
:将Map中的键值对复制到本Map中;Object remove(Object key)
:删除指定的key对应的键值对,并返回被删除键值对的value,如果不存在,则返回null;boolean remove(Object key,Object value)
:删除指定键值对,删除成功返回true;int size()
:返回该Map里的键值对个数;
内部类Entry
Map中包括一个内部类Entry,该类封装一个键值对,常用方法:
Object getKey()
:返回该Entry里包含的key值;Object getvalue()
:返回该Entry里包含的value值;Object setValue(V value)
:设置该Entry里包含的value值,并设置新的value值。
实例:
public static void main(String[] args) {
Map<String,String> map = new HashMap<String,String>();
map.put("1", "张三");
map.put("2", "李四");
map.put("3", "王五");
map.put("4", "陈六");
map.put("5", "赵七");
Set<Map.Entry<String,String>> set = map.entrySet();
Iterator it = set.iterator();
while(it.hasNext()){
System.out.println(it.next());
}
Set<String> setstring = map.keySet();
Iterator it1 = setstring.iterator();
while(it1.hasNext()){
System.out.println(it1.next());
}
Collection list = map.values();
Iterator it2 = list.iterator();
while(it2.hasNext()){
System.out.println(it2.next());
}
map.remove("2");
System.out.println(map);
}
二、HashMap
1.HashMap的特点
- HashMap中允许存放null键null值
- 线程不安全 –线程不同步
- 与HashTable类似
- Hashset是HashMap的实例 HashMap的底层是HashTable哈希表
- 在Java中 HashTable的父类是Dictionary
- 在1.7版本中底层数据结构是数组+链表,1.8版本是数组+链表+红黑树
2.HashMap和HashTable的区别
1、线程安全
两者最主要的区别在于Hashtable是线程安全,而HashMap则非线程安全。
Hashtable的实现方法里面都添加了synchronized关键字来确保线程同步,因此相对而言HashMap性能会高一些,我们平时使用时若无特殊需求建议使用HashMap,在多线程环境下若使用HashMap需要使用Collections.synchronizedMap()方法来获取一个线程安全的集合。
2、针对null的不同
HashMap可以使用null作为key,而Hashtable则不允许null作为key
虽说HashMap支持null值作为key,不过建议还是尽量避免这样使用,因为一旦不小心使用了,若因此引发一些问题,排查起来很是费事。
Note:HashMap以null作为key时,总是存储在table数组的第一个节点上。
3、继承结构
HashMap是对Map接口的实现,HashTable实现了Map接口和Dictionary抽象类。
4、初始容量与扩容
HashMap的初始容量为16,Hashtable初始容量为11,两者的填充因子默认都是0.75。
HashMap扩容时是当前容量翻倍即:capacity2,Hashtable扩容时是容量翻倍+1即:capacity2+1。
5、两者计算hash的方法不同
Hashtable计算hash是直接使用key的hashcode对table数组的长度直接进行取模
int hash = key.hashCode();
int index = (hash & 0x7FFFFFFF) % tab.length;
HashMap计算hash对key的hashcode进行了二次hash,以获得更好的散列值,然后对table数组长度取摸。
int hash = hash(key.hashCode());
int i = indexFor(hash, table.length);
static int hash(int h) {
// This function ensures that hashCodes that differ only by
// constant multiples at each bit position have a bounded
// number of collisions (approximately 8 at default load factor).
h ^= (h >>> 20) ^ (h >>> 12);
return h ^ (h >>> 7) ^ (h >>> 4);
}
static int indexFor(int h, int length) {
return h & (length-1);
实例:
public static void main(String[] args) {
Map<String,String> map = new HashMap<String,String>();
map.put("1", "张三");
map.put("2", "李四");
map.put("3", "王五");
map.put("4", "陈六");
map.put("5", "赵七");
Set<Entry<String,String>> set = map.entrySet();
Iterator it = set.iterator();
while(it.hasNext()){
System.out.println(it.next());
}
Set<String> setstring = map.keySet();
Iterator it1 = setstring.iterator();
while(it1.hasNext()){
System.out.println(it1.next());
}
Collection list = map.values();
Iterator it2 = list.iterator();
while(it2.hasNext()){
System.out.println(it2.next());
}
map.remove("2");
System.out.println(map);
}