Map接口是用于存储键值对映射关系的接口。Map接口提供了一种通过键来访问值的方式,Map中的每个键都是唯一的,值可以重复。
Map接口常用实现类:HashMap、TreeMap,LinkedHashMap等。
public HashMap( ):默认初始化容量是16,默认的加载因子是0.75,扩容比例是2倍扩容。
public HashMap( int initialCapacity ):可以对容量进行设置,加载因子默认是0.75.
Map.of( ):返回一个不可修改的集合对象。
containsValues( ):需要重写equals方法。
put( ):如果key不存在映射,把key和value放进Map中,返回null,如果key存在,用新的value覆盖旧的value,并返回旧的value。
compute(K key, BiFunction super K,? super V,? extends V> remappingFunction):无论key是否 存在,都会进入apply( )。
HashMap hashMap = new HashMap<>();
hashMap.put(1, new TVPlay("甄嬛传", 74));
hashMap.put(2, new TVPlay("长风渡", 40));
hashMap.put(3, new TVPlay("莲花楼", 40));
hashMap.put(4, new TVPlay("长相思", 40));
hashMap.put(5, new TVPlay("长相思", 40));
TVPlay compute = hashMap.compute(6, new BiFunction() {
@Override
public TVPlay apply(Integer key, TVPlay value) {
System.out.println("key" + key);
System.out.println("value" + value);
// TVPlay hj = new TVPlay("回家的诱惑", 80);
return null;
}
});
System.out.println(compute); // null
System.out.println(hashMap.containsKey(6)); // false
System.out.println(hashMap.get(6)); // null
System.out.println(hashMap);
computeIfAbsent(K key, Function super K,? extends V> mappingFunction)
TVPlay tvPlay = hashMap.computeIfAbsent(7, new Function() {
@Override
public TVPlay apply(Integer key) {
System.out.println(key);
return new TVPlay("长月烬明", 40);
}
});
System.out.println(tvPlay); // 长月烬明
System.out.println(hashMap.containsKey(7)); // true
System.out.println(hashMap.get(7)); // 长月烬明
computeIfPresent(K key, BiFunction super K,? super V,? extends V> remappingFunction)
TVPlay t = hashMap.computeIfPresent(7, new BiFunction() {
@Override
public TVPlay apply(Integer integer, TVPlay tvPlay) {
System.out.println(integer);
System.out.println(tvPlay);
return new TVPlay("仙剑奇侠传", 37);
}
});
System.out.println(t); // 仙剑
System.out.println(hashMap.containsKey(7)); // true
System.out.println(hashMap.get(7)); // 仙剑
merge(K key, V value, BiFunction super V,? super V,? extends V> remappingFunction)
TVPlay t1 = hashMap.merge(7, new TVPlay("庆余年", 56), new BiFunction() {
@Override
public TVPlay apply(TVPlay tvPlay, TVPlay tvPlay2) {
System.out.println(tvPlay); // 仙剑
System.out.println(tvPlay2); // 庆余年
return tvPlay2;
}
});
System.out.println(t1); // 庆余年
System.out.println(hashMap.containsKey(7));
System.out.println(hashMap.get(7));
HashMap底层数据结构:哈希表 ,JDK8之前的哈希表:数组+链表,JDK8之后的哈希表:数组+链表+红黑树。哈希表是一种增删改查,性能相对较好的数据结构。
底层数组默认长度为16,如果数组中长度超过阈值(阈值 = 初始容量*负载因子),就会对数组进行2倍扩容。
从HashMap底层存储元素的过程可以发现,决定键是否重复依赖于两个方法,hashCode(),equals(),两个键的hash值重复,并且equals返回true,就认为键重复。
Hashtable是Java中的一种哈希表数据结构,实现类Map接口,提供了键值对检索和存储的功能。
动态扩容:Hashtable在存储键值对的数量超过阈值(初始容量*负载因子)时会自动扩容,2倍+1扩容。
public Hashtable( ):使用默认初始容量 (11) 和负载因子 (0.75) 构造一个新的空集合对象
public Hashtable( int capacity ):指定初始容量
public Hashtable( int capacity , Float loadFactor):指定初始容量和负载因子
获取键的枚举(和比较器类似)
获取值的枚举(和比较器类似)
//获取值的枚举
Enumeration elements = hashtable.elements();
while (elements.hasMoreElements()){ //此枚举类中是否还有元素
String s = elements.nextElement(); //获取当前的元素
System.out.println(s);
}
//获取键的枚举
Enumeration keys = hashtable.keys();
while (keys.hasMoreElements()){
System.out.println(keys.nextElement());
}
都实现了Map接口,都存储的是键值对
特点:有序,不重复,无索引。
//如果access设置成true,会按照访问顺序排序
//被访问过的会被放到尾部,最后一个被访问的放到最后一个
LinkedHashMap linkedHashMap = new LinkedHashMap<>(160,0.75f,true);
linkedHashMap.put(1,"王鹤棣");
linkedHashMap.put(2,"李雪琴");
linkedHashMap.put(3,"小辣");
linkedHashMap.put(4,"汪苏泷");
linkedHashMap.put(5,"徐志胜");
linkedHashMap.put(6,"郭麒麟");
System.out.println(linkedHashMap.get(5));
System.out.println(linkedHashMap.get(2));
//能直接打印是因为LinkedHashMap的父类重写了toString
// System.out.println(linkedHashMap);
Set> entries1 = linkedHashMap.entrySet();
for (Map.Entry entry : entries1) {
System.out.println(entry.getKey() + "---->" + entry.getValue());
}
public LinkedHashMap( ):默认初始容量16,负载因子0.75
public LinkedHashMap( int capacity ):指定初始容量
public LinkedHashMap( int capacity, Float loadFactor ):指定初始容量和负载因子
public LinkedHashMap( int capacity, Float loadFactor, Boolean access ):指定初始容量和负载因子,设置按照访问顺序排序。
Collection values = map.values(); // 值的集合
System.out.println(values);
Set set = map.keySet();
Iterator iterator = set.iterator();
while (iterator.hasNext()) {
String key = iterator.next();
Integer value = map.get(key);
System.out.println(key + "-->" + value);
}
map.values( ):返回map中所有值的集合。
map.keySet():获取所有键的Set集合。
// entrySet() 获取到 map 中所有的键值对
// Set
// Set 中存储的对象类型是 Map.Entry
Set> entrySet = map.entrySet();
for (Map.Entry entry : entrySet) {
// Map.Entry 存储的是key和value
System.out.println(entry.getKey() + "==" + entry.getValue());
}
Map中所有的键值对都放到了entrySet集合中。
使用forEach遍历:
map.forEach(new BiConsumer() {
@Override
public void accept(String key, Integer value) {
System.out.println(key);
System.out.println(value);
System.out.println(key + "==" + value);
}
});
// map.forEach((key, value) -> System.out.println(key + "-->" + value));
public static void main(String[] args) {
//某个班级80名学生,有ABCD四个景点,统计想去哪个景点的人数最多
//假设把所有人的选择看成一个长度为80的字符串
String choice = "abbbcccd";
HashMap hashMap = new HashMap<>();
for (int i = 0; i < choice.length(); i++){
char c = choice.charAt(i);
if(hashMap.containsKey(c + "")){
Integer value = hashMap.get(c + "");
hashMap.put(c + "",value + 1);
}else {
hashMap.put(c + "",1);
}
}
int max = 0;
String str = "";
Set> entries = hashMap.entrySet();
for (Map.Entry entry : entries) {
if(max < entry.getValue()){
max = entry.getValue();
str = entry.getKey();
}
}
System.out.println("最想去的景点是:" + str);
System.out.println(hashMap);
}
TreeMap集合的特点也是有键决定的,默认按照键的升序排序, 键不重复,也是无索引。
public TreeMap( ):默认容量和负载因子
注意:只有TreeMap的键才能排序,HashMap的键不能排序。