HashMap
HashMap的实现原理
- 基于哈希表(数组+链表+二叉树(红黑树))
- 默认加载因子为0.75,默认数组大小是16
- 把对象存储到哈希表中,如何存储?
- 把key对象通过hash()方法计算hash的值,然后用这个hash值对数组长度取余数(默认是16),来决定对key对象在数组中存储的位置,当这个位置有多个对象时,以链表结构存储,JDK1.8后,当链表长度大于8时,链表转换为红黑树结构存储
- 这样的目的是为了取值更快,存储的数据量越大,性能的表现越明显
- 扩充原理:当数组的容量超过75%,数组需要进行扩充,如何扩充
- 扩充的算法是:当前容量乘以2,扩充次数过多,会影响性能,每次扩充表示哈希表重新散列(重新计算每个位置的存储位置),我们尽量在开发中减少扩充次数带来的性能问题。
- 线程不安全,适合在单线程里使用
简单使用:
实体类对象:
class Dog { private int id; private String name; public Dog() { } public Dog(int id, String name) { this.id = id; this.name = name; } // get,set,toString @Override public boolean equals(Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } Dog dog = (Dog) o; return id == dog.id && Objects.equals(name, dog.name); } @Override public int hashCode() { return Objects.hash(id, name); } }
private static void hashMap() { Map<Integer, String> map = new HashMap<>(); map.put(1, "jack"); map.put(2, "vince"); map.put(3, "bin"); map.put(4, "tom"); map.put(null, null); map.put(5, null); System.out.println(map.size()); // 从map遍历1 map.entrySet().forEach(System.out::println); // map遍历2 Set<Integer> integers = map.keySet(); for (Integer integer : integers) { System.out.println(map.get(integer)); } //map的遍历3(遍历值) map.values().forEach(System.out::println); // map的遍历4 map.forEach((integer, s) -> System.out.println(integer + "->" + s)); }
Hashtable:
- JDK1.0开始
- 基于哈希表(数组+链表)
- 默认数组大小为11,加载因子0.75
- 扩充方式:原数组大小*2+1
- 线程安全的,用在多线程访问时
简单使用:
private static void hashtable() { Map<String, String> table = new Hashtable<>(); table.put("one", "lili"); table.put("two", "lalal"); table.put("three", "zzz"); table.forEach((s, s2) -> System.out.println(s + "->" + s2)); }
TreeMap:
- 基于二叉树的红黑树实现,方便进行排序
简单应用
private static void treeMap() { Map<String, String> map = new LinkedHashMap<>(); map.put("one", "lili"); map.put("two", "lalal"); map.put("three", "zzz"); map.forEach((s, s2) -> System.out.println(s + "->" + s2)); Map<Dog, String> dogs = new TreeMap<>(Comparator.comparing(Dog::getId)); dogs.put(new Dog(1, "1ha"), "dog1"); dogs.put(new Dog(2, "2ha"), "dog2"); dogs.put(new Dog(3, "3ha"), "dog3"); dogs.forEach((s, s2) -> System.out.println(s + "->" + s2)); }
LinkedHashMap:
- LinkedHashMap是HashMap的子类,由于HashMap不能保证顺序恒久不变,此类使用一个双重链表来维护元素添加的顺序
简单使用
private static void linkedHashMap() { Map<String, String> map = new LinkedHashMap<>(); map.put("one", "lili"); map.put("two", "lalal"); map.put("three", "zzz"); map.forEach((s, s2) -> System.out.println(s + "->" + s2)); }