HashMap,TreeMap,Hashtable,LinkedHashMap的区别
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));
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!