-
Map用于保存具有映射关系的数据(Set集合也有这样的特点,只不过value的值是规定好的)
-
Map中的key和value可以是任意数据类型的,会封装到HashMap$Node对象中;
-
Map中的key是不允许重复的,原因和HashSet一样
-
Map 中存入相同的key值元素,会产生替换的效果,将原来的key值得数据进行替换
Map map = new HashMap(); map.put("001","jack"); map.put("002","tom"); map.put("001","jerry"); System.out.println(map); // {001=jerry, 002=tom} -
Map中的value是可以重复的,
-
Map中key可以为null,value也可以为null,注意key为null的只有一个,value可以有多个null值
-
常用String作为Map中的key其他类型可以,因为他是Object类型的
-
key 和value直接存在单一对应关系,既可以通过key值总能找到对应的value值
-
map接口中的常用方法:
- put(); 添加
- remove方法:
- get()
- isEmpty
- size()
- clear()
- containsKey()
-
增强for循环
Map map = new HashMap(); map.put("122",12); map.put("123",13); map.put("124",14); Set set = map.keySet(); for(Object item : set){ sout(item + "-" + map.get(item)); } -
迭代器
Map map = new HashMap(); map.put("122",12); map.put("123",13); map.put("124",14); Set set = map.keySet(); Iterator iterator = set.iterator(); while (iterator.hasNext()) { Object key = iterator.next(); System.out.println(key + "-" + map.get(key)); }
-
增强for
Map map = new HashMap(); map.put("122",12); map.put("123",13); map.put("124",14); Collection values = map.values(); for (Object item : values) { System.out.println(item); } -
迭代器
Map map = new HashMap(); map.put("122",12); map.put("123",13); map.put("124",14); Collection values = map.values(); Iterator iterator = values.iterator(); while (iterator.hasNext()) { Object next = iterator.next(); System.out.println(next); }
-
增强for
Map map = new HashMap(); map.put("122",12); map.put("123",13); map.put("124",14); Set set = map.entrySet(); for (Object entry : set) { Map.Entry item = (Map.Entry) entry; System.out.println(item.getKey() + " " + item.getValue()); } -
迭代器
Map map = new HashMap(); map.put("122",12); map.put("123",13); map.put("124",14); Set set = map.entrySet(); Iterator iterator = set.iterator(); while (iterator.hasNext()) { Map.Entry entry = (Map.Entry) iterator.next(); System.out.println(entry.getKey() + " " + entry.getValue()); }
扩容机制
-
HashMap底层维护了一个Node类型的数组table,默认为null
-
当创建对象时,加载因子初始化为0.75,
-
当添加key -value时,通过key的哈希值,得到在table中的索引然后判断该索引处是否有元素,如果没有元素直接添加,如果该索引处有元素,继续判断元素元素的key和准备加入的key值是否相等,则直接替换为value,如果不同需要判断是树结构还是链表结构,做出相应的处理,如果添加是发现容量不够,则需要扩容
-
第一次添加,需要table容量为16,临界值为12,(16 * 0.75)
-
以后再次扩容是,按照原来的两倍(32),临界值为(32 * 0.75) = 24;
-
在java8 中如果一条链表的元素超过8个,并且table的大小,大于等于64,就会进行树化(红黑树)
-
代码解读
注意:
- 扩容是(开始为16),如果在某一条链上的个数等于8是,在该链上加一个,会将table容量为32,在加一个,或扩容为64,在加一个就会转化为红黑树;
- 存放的是键值对
- hashtable的键和值不能为null,
- hashtable使用方法基本上和HashMap一样
- HashTable是线程安全,HashMap非线程安全
-
.底层是一个数组 + 链表
-
初始化的长度为11;
-
临界值为0.75 =* 11 = 8;
-
扩容:
第一次为11;
第二次为11 * 2 + 1 = 23;
| HashMap | HashTable | |
|---|---|---|
| 版本 | 1.2 | 1.0 |
| 线程安全 | 非线程安全 | 线程安全 |
| 效率 | 高 | 较低 |
| 允许null键和null值 | 可以 | 不可以 |
| 初始的容量和每次扩容的大小不同 | 默认为null,第一次添加,初始为16,扩容为原来的2倍 | 默认为长度为11,扩容为原来的两倍 + 1; |
| 计算Hash值得方式不同 | 是使用自定义的哈希算法。 | 没有自定义哈希算法,而直接采用的key的hashCode() |
- 在构造方法中可以传入比较器
- 可以进行排序
- 存放的是键值对
- 基于红黑树对所有的的key进行排序
- 自然排序和定值排序
- 底层是红黑树



