Map集合key和Set集合特性一样–本质上Set集合就是在使用Map集合,所以直接参考Set集合来理解Map
- Map是一种具有映射关系的键值对数据集合,集合中保存着两组值:key和value
- key和value可以是任何引用类型的数据(对象)
- key值不允许重复–如果重复添加会覆盖先前添加的数据–key的特性和Set一样:无序不可重复
- Set接口中的很多实现类,基本上都是使用了对应的Map实现类
- value是一个Collection集合组,无序的原因是因为key决定了value的排序顺序
当Map中存放的元素是基本数据类型时会自动装箱
常用方法:
void clear():删除该Map对象中的所有key-value对
boolean containKey(Object key):查询Map中是否包含指定的key,如果包含返回true
boolean containValue(Object value):查询Map中是否包含指定的value,如果包含返回true
Set entrySet():返回Map中包含的key-value对所组成的Set集合,每个元素都是MapEntry(Entry是Map的内部类)对象 Set<Map.Entry<String, Integer>> entries = hm.entrySet();
Object get(Object key):返回指定的key对应的value值,如果key值不存在则返回null
boolean isEmpty():判断Map集合是否为空,为空返回true
Set keySet():返回该Map中所有的key组成的set集合
Collection values():返回该Map里所有的value组成的Collection集合
Object put(Object key,Object value):添加一个key-value对,如果当前的Map中已经有一个与该key值相等的key-value对,则新的key-value会覆盖原来的key-value对
void putAll():将指定的Map中的key-value添加到当前Map中,指定了泛型后集合A和集合B元素类型一定要一致
boolean remove(Object key,Object value):JDK8新增方法,删除指定key,value参数值所对应的key-value对,如果删除成功则返回true
Object remove(Object key):删除指定key值所对应的key-value对,返回被删除的key所关联的value,如果key不存在返回null
int size():返回该Map里的key-value对的个数
Entry内部类包含三个方法:
Object getKey():返回该Entry里包含的key值
Object getValue():返回该Entry里包含的value值
Object setValue():设置该Entry里包含的value值,并返回新设置的value值--这里不是临时修改,而是真实修改了Map集合的内容
JDK8以后新增方法:
Object compute(Object key,BiFunction remappingFunction):该方法使用remappingFunction根据原key-value对计算一个新的value,只要value不为null,就使用新的value覆盖原value;如果原value不为null,但是新的value为null,则删除原key-value对;如果原value和新value都为null,则不改变key-value,返回null
Object computeIfAbsent(Object key,BiFunction mappingFunction):如果key对应的Map集合中的key-value中key对应的value为null,则使用mappingFunction根据key对计算一个新的value,只要计算的结果不为null,就覆盖原有的key-value,如果原Map没有对应的key,则可能添加一组新的key-value
Object computeIfPresent(Object key,BiFunction remappingFunction):如果key对应的Map集合中的key-value中key对应的value为null,则使用mappingFunction根据原key、value对计算一个新的value,如果新的value不为null,则使用新的覆盖旧的,如果计算结果为null,则删除原有key-value对
void forEach(BiConsumer action):Map集合的遍历,使用lambda表达式,BiConsumer是一个函数式接口
Object merge(Object key,Object value,BiFunction remappingFunction):该方法会先根据key参数获取该Map中对应的value,如果获取的value为null,则直接用传入的value值覆盖原有value;如果获取的value不为null,则使用remappingFunction函数根据原value、新value计算一个新的结果,并用得到的结果去覆盖原有value
Object getOrDefault(Objecy key,V DefaultValue):获取指定key对应的value,如果该key不存在则返回defaultValue
Object putIfAbsent(Object Key,Object value):该方法会自定检测指定的key对应的value是否为null,如果该key对应的value为null,该方法将会用新value代替原有的null值
Object replace(Object key,Object value):将Map中指定key对应的value替换为新的value值,与put方法不同的是,该方法不是采用覆盖的方式进行添加的,如果key值不存在,则不会添加新的key-value,而是返回null
boolean replace(K key,V oldValue,V newValue):将Map中指定的key-value对的原value替换为新的value,如果在Map中找到指定的key-value对,则执行替换并返回true,否则返回false
replaceAll(BiFunction function):该方法使用BiFUnction对原key-value对执行计算,并将计算结果作为该key-value对的value值
package com.carl.javaadvanced.map_demo;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
public class HashMapTest {
public static void main(String[] args) {
HashMap<String, Integer> hm= new HashMap<>();
//HashMap允许key-value值为null
hm.put(null, 5);
hm.put("张三", null);
// hm.put(null,null);//如果key相等,后面put的值将会覆盖前面put的值
hm.forEach((key,value)-> System.out.println("键"+key+"值"+value));
hm.put("李四", 20);
//清空Map集合
// hm.clear();
//判断key值是否存在于Map集合中
System.out.println(hm.containsKey("张三"));//true
//判断value值是否存在于Map集合中
System.out.println(hm.containsValue(15));//false
//返回key-value对应关系的Set集合,如:李四=20,这样的集合由Map的Entry内部类进行维护
Set<Map.Entry<String, Integer>> entries = hm.entrySet();
for (Map.Entry<String, Integer> entry : entries) {
//Entry的三个方法:
System.out.println("Entry>>>>>>>>>>>>>>>>>>>>>>");
System.out.println(entry.getKey());
System.out.println(entry.getValue());
if ("张三".equals(entry.getKey()))
entry.setValue(15);
System.out.println("Set集合:"+entry);
}
System.out.println("****************");
//获取指定key对应的value值
System.out.println(hm.get("李四"));//20
//判断当前Map集合是否为空,如果为空则返回true,否则返回false
System.out.println(hm.isEmpty());//false
//使用Set集合存储Map中所有的key值
Set<String> strings = hm.keySet();
for (String string : strings) {
System.out.println(string);
}
//使用Collection集合存储Map集合中的所有value值
Collection<Integer> values = hm.values();
for (Integer value : values) {
System.out.println(value);
}
//Exception in thread "main" java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer
Map map=new HashMap();
map.put("杜甫", "刘备");
Map map1=new HashMap();
map.put("李白", 15);
map1.putAll(map);
//删除该key值对应的value值,删除成功,返回删除key-value对应的value值,失败返回null
// System.out.println("remove:"+map1.remove("杜甫"));
//删除对应的map对应的key-value值,删除成功返回true
System.out.println("remove:"+map1.remove("杜甫","刘备"));
//返回Map集合key-value对个数
System.out.println(hm.size());//3
//删除该key-value对应的key-value
hm.forEach((key,value)-> System.out.println("键"+key+"值"+value));
// map1.forEach((key,value)-> System.out.println("键"+key+"值"+value));
//JDK8新增方法测试
System.out.println("*******************<><><><><><><><><>**********************");
Map<String,Integer> map2=new HashMap<>();
map2.put("刘备", 15);
map2.put("关羽", 20);
map2.put("张飞", 16);
map2.put("赵云", 19);
map2.put("马超", 17);
map2.put("黄忠", 46);
map2.put("李白", null);
map2.put("杜甫", null);
//compute方法的使用--修改value值
//1.如果key找不到,空指针异常NullPointerException
//2.如果key找得到,只要修改后的value不为null,覆盖并返回修改后的value
// System.out.println(map2.compute("刘备", (key, value) -> (value * value)));
// System.out.println(map2.compute("刘备", (key, value) -> value));
// System.out.println(map2.compute("李白", (key, value) -> 15));
// //3.只要修改后的value为null,则删除原有key-value,并返回null
// System.out.println(map2.compute("刘备", (key, value) -> null));
// System.out.println(map2.compute("杜甫", (key, value) -> null));
map2.forEach((key,value)-> System.out.println(key+"="+value));
//computeIfAbsent
System.out.println("*******************<><><><><><><><><>**********************");
//1.如果key不存在,则添加到map中
// System.out.println(map2.computeIfAbsent("曹操", (key) -> 20));
// //2.如果是原value值为null,新value替换旧value
// System.out.println(map2.computeIfAbsent("杜甫", (key) -> 20));
// //3.如果原value值不为null,新value并不会对旧value进行覆盖
// System.out.println(map2.computeIfAbsent("黄忠", (key) -> 20));
//
// map2.forEach((key,value)-> System.out.println(key+"="+value));
//computeIfPresent
System.out.println("*******************<><><><><><><><><>**********************");
//1.如果key不存在,则返回null--不会添加
System.out.println(map2.computeIfPresent("曹操", (key,value) -> 20));
//2.key存在,原value值为null,计算不生效-返回null
System.out.println(map2.computeIfPresent("杜甫", (key,value) -> null));
//3.原value不为null,新value也不为null,由修改后的key-value覆盖旧key-value
System.out.println(map2.computeIfPresent("黄忠", (key,value) -> 20));
//4.只要修改后的value为null则删除该key-value
System.out.println(map2.computeIfPresent("黄忠", (key,value) -> null));
map2.forEach((key,value)-> System.out.println(key+"="+value));
}
}
上述代码是部分测试代码
Map集合
总结Map性能
-
HashMap和Hashtable实现机制一样,但是Hashtable是线程安全的集合,性能慢于HashMap
-
TreeMap通常比HashMap和Hashtable要慢(尤其是在插入和删除的时候),因为使用了红黑树来维护元素的次序
-
使用TreeMap的好处:key-value总是有序状态,无序专门进行排序,可以通过调用keySet(),取得key的Set集合,,然后通过toArray()方法将Set集合转换为数组,最后通过Arrays工具类中的binarySearch()方法在已排序的数组中快速查询对象
-
linkedHashMap比HashMap慢,因为它需要维护一张链表,来保持每次取数都是按照添加顺序
-
IdentityHashMap性能和HashMap相似,只是判断相等的标准不一致
-
EnumMap的性能最好,但是只能存储同一个枚举值类的不同枚举值