第32 章 : Map集合
139 Map接口简介
二元偶对象(key=value)
Collection集合保存数据是为了输出
Map集合保存数据是为了key查找
常用方法
put 添加数据 get 获取数据 entrySet 将Map转为Set containsKey 检查存在 keySet 将Map中的key转为Set remove 删除数据
继承关系
@Map -@SortedMap -@NavigableMap AbstractMap(Map) -HashMap(Map, Cloneable, Serializable) -LinkedHashMap(Map) -TreeMap(NavigableMap, Cloneable, Serializable) Dictionary -Hashtable(Map, Cloneable, Serializable)
140 HashMap子类
hash 无序
tree 有序
HashMap 无序存储
import java.util.HashMap; import java.util.Map; class Demo { public static void main(String[] args) { Map<String, String> map = new HashMap<>(); map.put("one", "one"); map.put("one", "one+"); // key重复 会被覆盖 map.put("two", null); // value 为null map.put(null, "three"); // key 为null System.out.println(map.get("one")); // key重复 one+ System.out.println(map.get("two")); // key存在 null System.out.println(map.get("ten")); // key不存在 null } }
put会返回原来的value
Map<String, Integer> map = new HashMap<>(); System.out.println(map.put("one", 1)); // null System.out.println(map.put("one", 101)); // key重复 1
面试题:HashMap容量扩充
初始容量为16个元素,超过了阈值0.75 相当于 容量 * 阈值 = 12,会自动扩充
扩充的时候会成倍扩充
面试题:HashMap工作原理
链表O(n)
二叉树O(logn)
JDK < 1.8 链表O(n)
JDK >= 1.8 链表O(n) 数量大于8个元素后变为 红黑树,保证查询性能
141 LinkedHashMap子类
LinkedHashMap(链表实现)按照添加顺序保存数据
import java.util.HashMap; import java.util.LinkedHashMap; import java.util.Map; class Demo { public static void main(String[] args) { Map<String, Integer> map = new LinkedHashMap<>(); map.put("two", 2); map.put("one", 1); map.put("three", 3); System.out.println(map); // HashMap {one=1, two=2, three=3} // LinkedHashMap {two=2, one=1, three=3} } }
142 Hashtable子类
与Vector,Enumeration属于最早的动态数组实现类
Hashtable key 和value都不能为null
import java.util.Hashtable; import java.util.Map; class Demo { public static void main(String[] args) { Map<String, Integer> map = new Hashtable<>(); map.put("two", 2); map.put("one", 1); map.put("three", 3); System.out.println(map); // {two=2, one=1, three=3} } }
面试题:HashMap与HashTable区别
HashMap 异步操作,非线程安全, 允许null HashTable 同步操作,线程安全,不允许null
143 Map.Entry内部接口
Map.Entry 作为一个key,value的包装
JDK >= 1.9
144 利用Iterator输出Map集合
存储结构
Collection(Iterator) Map vlaue Map.Entry(key, value) vlaue Map.Entry(key, value)
Map对象迭代方式
Map - entrySet() -> Set Set - iterator() -> Iterator Iterator -> Map.Entry
import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.Set; class Demo { public static void main(String[] args) { Map<String, Integer> map = new HashMap<>(); map.put("Tom", 20); map.put("Jack", 21); // 1、将Map转Set Set<Map.Entry<String, Integer>> set = map.entrySet(); // 2、将Set 转Iterator Iterator<Map.Entry<String, Integer>> iterator = set.iterator(); while (iterator.hasNext()){ Map.Entry<String, Integer> entry = iterator.next(); System.out.println(entry.getKey() + "= "+ entry.getValue()); } /** * Tom= 20 * Jack= 21 */ } }
简化写法
import java.util.HashMap; import java.util.Map; class Demo { public static void main(String[] args) { Map<String, Integer> map = new HashMap<>(); map.put("Tom", 20); map.put("Jack", 21); for(Map.Entry<String, Integer> entry: map.entrySet()){ System.out.println(entry.getKey() + "= "+ entry.getValue()); } /** * Tom= 20 * Jack= 21 */ } }
145 自定义Map的key类型
通过key获取hash码
常用key:
String Integer Long
面试体:HashMap出现Hash冲突
Hash冲突会转为链表
key key key(hash冲突) value value value value value
import java.util.HashMap; import java.util.Map; import java.util.Objects; class Person{ private String name; private int age; public Person(String name, int age) { this.name = name; this.age = age; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Person person = (Person) o; return age == person.age && Objects.equals(name, person.name); } @Override public int hashCode() { return Objects.hash(name, age); } } class Demo { public static void main(String[] args) { Map<Person, Integer> map = new HashMap<>(); map.put(new Person("Tom", 20), 20); System.out.println(map.get(new Person("Tom", 20))); // 20 } }