Map详解
1、map集合概述
public interface Map
首先看一下map接口,我们可以看到map的存值结构以键值对结构,简单来说,map集合就是一个将键(key)映射到值(value)的对象且一个映射不可以包含重复的键,每个键只能映射到一个值。
2、map的存储结构
如上图所示,map中存储数据的方式是一个key对应一个value值
所有key不能重复,没有顺序,相当于一个Set集合。
key值可为null,但由于key的值不可重复,故key为null的情况也只可以有一次
value的值可以重复也可以多个为null
一对键值对底层是放在一个entry数组中
查询的时候是根据键(key)键的值的hashcode值找寻value所对应的位置,如果对同一个键多次赋value的值,那么后赋的值会覆盖前面赋的值.
3、总结一下map的一些特点
Map集合是一个双列集合,一个元素包含两个值(一个key,一个value)。
Map集合中的元素,key和value的数据类型可以相同,也可以不同。
Map集合中的元素,key是不允许重复的, value是可以重复的。
Map集合中的元素,key和 value是一一对应的。
4、map的实现类
下面挑几个比较常用的实现类来讲解
4.1 HashMap
这是我们日常使用比较多的一个实现类. 它的底层实现方式是数组+链表,key和value的值都可以为null. 初始的内存大小为16,一般存储元素到达大小的一半的时候进行扩容. 线程不安全,但优点在于效率比较高. HashMap不支持同步,即同一时刻多个线程同时进行写操作是可能会导致数据的不一致,若需要支持同步的话,可以使用collections的synchronizedmap方法.
4.2 Hashtable
它的底层实现是数组+链表,key和value不可以存储null. 因为给大多数的操作都加了锁的缘故,所以Hashtable支持同步操作,但也正是这一点,导致了Hashtable的写入速度较慢,在对于数据的安全级别要求较高的时候使用.
4.3 ConcurrentHashMap
它的底层实现是分段数组+链表. Hashtable的synchronized是针对整张Hash表的,即每次锁住整张表让线程独占
ConcurrentHashMap允许多个修改操作并发进行,其关键在于使用了锁分离技术 通过把整个Map分为N个Segment,可以提供相同的线程安全,但是效率提升N倍,默认提升16倍.
4.4 linkedHashMap
LinkedHashMap可以认为是HashMap和LinkedList合体,即它既使用HashMap操作数据结构,又使用LinkedList维护插入元素的先后顺序. 内部维持了一个双向链表. LinkedHashMap是HashMap的子类. 它的元素按照插入顺序排列. 遍历速度较慢.
4.5 TreeMap
基于红黑树(Red-Black tree)的 NavigableMap 实现.该映射根据其键的自然顺序进行排序,或者根据创建映射时提供的 Comparator 进行排序.具体取决于使用的构造方法。优点是键值可排序,唯一,值有序可重复,底层数据结构是平衡二叉树.
5、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值。
HashMap<String, Integer> hm = new HashMap<>();
//放入元素
hm.put("Harry",23);
hm.put("Jenny",24);
hm.put("XiaoLi",20);
System.out.println(hm);//{XiaoLi=20, Harry=23, Jenny=24}
System.out.println(hm.keySet());//[XiaoLi, Harry, Jenny]
System.out.println(hm.values());//[20, 23, 24]
Set<Map.Entry<String, Integer>> entries = hm.entrySet();
for (Map.Entry<String, Integer> entry : entries) {
System.out.println(entry.getKey());
System.out.println(entry.getValue());
}
}
6、java8为Map新增的方法
default V getOrDefault(Object key, V defaultValue)
default void forEach(BiConsumer<? super K, ? super V> action)
default V putIfAbsent(K key, V value)putIfAbsent
Object compute(Object key,BiFurcation remappingFunction)
computeIfAbsent
computeIfPresent
merge
remove(key,value)
replace
replaceAll
getOrDefault
如果Map中不存在该key,可以提供一个默认值,方法会返回改默认值。如果存在该key,返回键对应的值。
java8之前的写法:
Map<String, String> map = new HashMap<>();
String value = "D";
if(map.containsKey("d")) {
value = map.get("d");
}
java8:
String value = map.getOrDefault("d", "D");
forEach
default void forEach(BiConsumer<? super K, ? super V> action)
forEach遍历map,对map中的每个映射执行action指定的操作。
Map<String, String> map = new HashMap<>();
map.put("a", "A");
map.put("b", "B");
// 遍历
map.forEach((k, v)-> {
System.out.println(k + "=" + v);
map.put(k, k + v);
});
// 输出
// a=A
// b=B
map.forEach((k, v)-> {
System.out.println(k + "=" + v);
});
// 输出
// a=aA
// b=bB
putIfAbsent
default V putIfAbsent(K key, V value)
V putIfAbsent(K key, V value)只有在不存在key值的映射或者映射值为null,才将value值赋值给key。否则不做修改。该方法将条件判断和赋值合二为一。
Map<String, String> map = new HashMap<>();
map.put("a", "A");
map.put("b", "B");
String e = map.putIfAbsent("e", "E");
String b = map.putIfAbsent("b", "E");
System.out.println("返回e="+e); //返回e=null
System.out.println("键e="+map.get("e"));//键e=E
System.out.println("返回b="+b);//返回b=B
System.out.println("键b="+map.get("b"));//键b=B
remove(key,value)
default boolean remove(Object key, Object value)
只有在当前Map中key映射的值等于value时才删除该映射,否则什么也不做。
Map<String, String> map = new HashMap<>();
map.put("a", "A");
map.put("b", "B");
map.remove("a", "B");
map.remove("b", "B");
System.out.println(map.get("a")); // A
System.out.println(map.get("b")); // null
replace(K key, V value)
只有在当前Map中包含key,才用value去替换原来的值,否则什么也不做。
Map<String, String> map = new HashMap<>();
map.put("a", "A");
map.put("b", "B");
map.replace("c", "1");
map.replace("b", "1");
System.out.println(map.get("c")); // null
System.out.println(map.get("b")); // 1
replace(K key, V oldValue, V newValue)
default boolean replace(K key, V oldValue, V newValue)
只有在当前Map中key的映射存在且映射的值等于oldValue时才用newValue去替换原来的值,否则什么也不做。
Map<String, String> map = new HashMap<>();
map.put("a", "A");
map.put("b", "B");
map.replace("a", "1", "2");
map.replace("b", "B", "2");
System.out.println(map.get("a")); // A
System.out.println(map.get("b")); // 2
replaceAll
default void replaceAll(BiFunction<? super K, ? super V, ? extends V> function) { Objects.requireNonNull(function);
该方法签名为replaceAll(BiFunction<? super K,? super V,? extends V> function),作用是对Map中的每个映射执行function指定的操作,并用function的执行结果替换原来的value
Map<String, String> map = new HashMap<>();
map.put("a", "A");
map.put("b", "B");
map.replaceAll((k, v) -> v.toLowerCase());
map.forEach((k, v)-> {
System.out.println(k + "=" + v);
});
// a=a
// b=b
merge
default V merge(K key, V value, BiFunction<? super V, ? super V, ? extends V> remappingFunction)
value和remappingFunction不能为null
如果Map中key对应的映射不存在或者为null,则将value关联到key上;否则执行remappingFunction,如果执行结果为null则删除key的映射,否则用该结果跟key关联。
Map<String, String> map = new HashMap<>();
map.put("e", "E");
map.merge("f", "F", String::concat);
map.merge("e", "F", String::concat);
System.out.println("map.get(\"f\")="+map.get("f")); // map.get("f")=F
System.out.println("map.get(\"e\")="+map.get("e")); // map.get("e")=EF
Object compute(Object key,BiFurcation remappingFunction)
default V compute(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction)
使用remappingFunction根据原键值对计算一个新的value,只要新value不为null,就覆盖原value;如果新value为null则删除该键值对,如果同时为null则不改变任何键值对,直接返回null。
Map<String, String> map = new HashMap<>();
map.put("b", "B");
map.put("c", "C");
map.put("d", "D");
String val = map.compute("b", (k, v) -> null);
System.out.println(val);
System.out.println(map);//{c=C, d=D}
String val2 = map.compute("e", (k, v) -> v + "+v");
System.out.println(val2);//null+v
System.out.println(map);//{c=C, d=D, e=null+v}
computeIfAbsent
default V computeIfAbsent(K key, Function<? super K, ? extends V> mappingFunction)
当Map中不存在key值的映射value或映射值value为null时,调用mappingFunction,并在mappingFunction执行结果非null时,将结果赋值给key。
比如(输入每个字母的位置):
List<String> list = Lists.newArrayList("a", "b", "b", "c", "c", "c", "d", "d", "d", "f", "f", "g");
Map<String, List<Integer>> positionsMap = new HashMap<>();
for (int i = 0; i < list.size(); i++) {
positionsMap.computeIfAbsent(list.get(i), k -> Lists.newArrayListWithCapacity(1)).add(i);
}
System.out.println(positionsMap);
// {a=[0], b=[1, 2], c=[3, 4, 5], d=[6, 7, 8], f=[9, 10], g=[11]}
HashMap<String, Integer> hm = new HashMap<>();
//放入元素
hm.put("Harry",23);
hm.put("Jenny",24);
hm.put("XiaoLi",20);
hm.put("LiMing",null);
//指定key为null则计算结果作为value
hm.computeIfAbsent("LiMing",(key)->10);
System.out.println(hm);//{XiaoLi=20, Harry=23, Jenny=24, LiMing=10}
//如果指定key本来不存在,则添加对应键值对
hm.computeIfAbsent("XiaoHong",(key)->34);
System.out.println(hm);//{XiaoLi=20, Harry=23, XiaoHong=34, Jenny=24, LiMing=10}
本文地址:https://blog.csdn.net/mingyuli/article/details/110292564
上一篇: 全国高校计算机能力挑战赛Java试题
下一篇: 单页面SEO怎么优化 单页面SEO技巧