map接口,是一种键值对的式的结构,开发中,经常使用这种结构
key:键,是唯一的,不能重复,若重复,则会覆盖原有key中的值(哈希表中是唯一的,不能 重复),所以用哈希表去维护,map之所以用hashmap的原因是要保证key的唯一性
value : 值 可以重复
注意:Map接口没有继承Collection
1. 常见方法:map是接口,不能实例化,所以得用它的子类
在java中,Map的key可以是任意类型(泛型)
1)添加V put(K key, V value);
当key重复时,不会创建多个键值对,只会进行覆盖
在HashMap中,可以使用null作为key
2)获取V get(Object key);
如果获取的key不存在,则返回空
import java.util.Map; @Test void testMap01() { Map3)getOrDefault、containsKey、remove、replacemps = 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() { Mapmps = 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); }
2. 遍历map结构
@Test void testMap03() { Mapmps = 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,再迭代数据 SetkeySet = 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));
二、Map的常见实现子类:
HashMap
Hashtable
ConcurrentHashMap
1. 三者区别和联系: 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之后进行优化,做了自旋锁,本质不是锁,所以效率更高。
2. HashMap简介:
它是一个标准的哈希表
JDK8之前,HashMap:整体结构是一个"数组 + 链表" 结构
JDK8之后,HashMap:整体结构是一个"数组 + 链表 + 红黑树" 结
1)、哈希冲突:(1).什么是哈希冲突
哈希冲突是指哈希函数算出来的地址被别的元素占用了。
(2).哈希冲突的四种解决方案:
1、再哈希法
2、开放定址法
3、链地址法
4、建立公共溢出区: