map接口,是一种键值对的式的结构,开发中,经常使用这种结构
key:键,是唯一的,不能重复,若重复,则会覆盖原有key中的值(哈希表中是唯一的,不能 重复),所以用哈希表去维护,map之所以用hashmap的原因是要保证key的唯一性
value : 值 可以重复
注意:Map接口没有继承Collection
map是接口,不能实例化,所以得用它的子类
在java中,Map的key可以是任意类型(泛型)
V put(K key, V value);
当key重复时,不会创建多个键值对,只会进行覆盖
在HashMap中,可以使用null作为key

V get(Object key);
![]()
如果获取的key不存在,则返回空
- import java.util.Map;
-
- @Test
- void testMap01() {
- Map
mps = new HashMap<>(); - mps.put("name", 123);
- mps.put("age", 23);
- mps.put("gender", 56);
-
- // 当key重复时,不会创建多个键值对,只会进行覆盖
- mps.put("gender", 100);
-
- System.out.println(mps);
- System.err.println(mps.size());
-
- System.err.println(mps.get("name"));
-
- // 如果获取的key不存在,则返回空
- System.err.println(mps.get("nickname"));
-
- // 在HashMap中,以null作为key,可以不?
- // 在HashMap中,可以使用null作为key
- mps.put(null, 123);
- System.out.println(mps);
- System.out.println(mps.get(null));
- }

- @Test
- void testMap02() {
- Map
mps = new HashMap<>(); - mps.put("name", "小豪");
- mps.put("age", "13");
- mps.put("gender", "男");
-
- // 获取时,如果存在,则返回,如果不存在,则给定一个默认值
- System.out.println(mps.getOrDefault("name2", "佚名"));
-
- //是否包含某个键
- System.out.println(mps.containsKey("name"));
- System.out.println(mps.containsKey("nickname"));
-
- // 根据key 移除整个键值对
- System.out.println(mps.remove("name"));
- System.out.println(mps);
-
- // 根据key和value,移除整个键值对,键和值都匹配才会移除
- System.out.println(mps.remove("age", "20"));
- System.out.println(mps);
- System.out.println(mps.remove("age", "13"));
- System.out.println(mps);
-
- // 注意,仅仅是替换key对应的值,如果没有,不会添加
- mps.replace("gender", "male");
- System.out.println(mps);
- mps.replace("gender1", "male");
- System.out.println(mps);
- }

- @Test
- void testMap03() {
- Map
mps = new HashMap<>(); - mps.put("name", "小豪");
- mps.put("age", 13);
- mps.put("gender", "男");
- mps.put("address", "汉中");
- }
1). keySet()
// 注意:这个方法错误,每当调一次next()就会向前走一次
// SetkeySet = mps.keySet();
// Iteratorkeys = keySet.iterator();
// while (keys.hasNext()) {
// System.out.println(keys.next() +"---->"+ mps.get(keys.next()));
// }
- //用这种方法进行迭代(迭代器)
- // keySet(),将map的key 做成set,再迭代数据
- Set
keySet = mps.keySet();//key是字符串,返回的set的类型是字符串类型 -
- Iterator
keys = keySet.iterator(); - while (keys.hasNext()) {
- String key = keys.next();
- System.out.println(key +"---->"+ mps.get(key));
- }
-
- //使用for循环加强简化迭代器
- for (String key : mps.keySet()) {
- System.out.println(key +"---->"+ mps.get(key));
- }
2).entrySet()
- //Entry返回的是map中的每一个键值对,返回的是set类型
-
- Set
> entrySet = mps.entrySet(); -
- //迭代器
- Iterator
> iterator = entrySet.iterator(); - while(iterator.hasNext()) {
- System.out.println(iterator.next());
- }
-
- // while(iterator.hasNext()) {
- // Entry
set = iterator.next(); - // System.out.println(set);
- // }
-
- //for循环加强
- for (Entry
entry : entrySet) { - System.out.println(entry.getKey() +"---->"+ entry.getValue());
- }
3).forEach()
// 使用lambda表达式,简化遍历操作
entrySet.forEach(t -> System.out.println(t.getKey() +"---->"+ t.getValue()));
//之前提到的forEach的写法都可以用
4).jdk8提供的新的map自身的一种遍历方式
mps.forEach((k, v) -> System.out.println(k +"---->"+ v));
HashMap
Hashtable
ConcurrentHashMap
HashMap 非线程安全 jdk1.2诞生
Hashtable(同步锁)线程安全 jdk1.0诞生
这个规则类似于线性表中的ArrayList和Vector
ArrayList 非线程安全 jdk1.2诞生
Vector(同步锁)线程安全 jdk1.0诞生
ConcurrentHashMap(Hashtable可以解决高并发,但随着技术的发展,用 ConcurrentHashMap) jdk1.5诞生 对HashMap进行改造,在HashMap中分段锁的机制
HashMap 默认由大小为16的数组组成,ConcurrentHashMap对每个节点进行加锁操作,相 当于加了16个分段锁,使得线程安全,但是效率比Hashtable至少高16倍。jdk8之后进行优化,做了自旋锁,本质不是锁,所以效率更高。
它是一个标准的哈希表
JDK8之前,HashMap:整体结构是一个"数组 + 链表" 结构
JDK8之后,HashMap:整体结构是一个"数组 + 链表 + 红黑树" 结
(1).什么是哈希冲突
哈希冲突是指哈希函数算出来的地址被别的元素占用了。
(2).哈希冲突的四种解决方案:
1、再哈希法
2、开放定址法
3、链地址法
4、建立公共溢出区: