HashMap,TreeMap,Hashtable,LinkedHashMap的区别

简介: 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));
    }


目录
相关文章
|
23天前
|
存储 Java
Java中的HashMap和TreeMap,通过具体示例展示了它们在处理复杂数据结构问题时的应用。
【10月更文挑战第19天】本文详细介绍了Java中的HashMap和TreeMap,通过具体示例展示了它们在处理复杂数据结构问题时的应用。HashMap以其高效的插入、查找和删除操作著称,而TreeMap则擅长于保持元素的自然排序或自定义排序,两者各具优势,适用于不同的开发场景。
38 1
|
25天前
|
存储 安全 Java
Java Map新玩法:探索HashMap和TreeMap的高级特性,让你的代码更强大!
【10月更文挑战第17天】Java Map新玩法:探索HashMap和TreeMap的高级特性,让你的代码更强大!
52 2
|
23天前
|
存储 Java API
详细解析HashMap、TreeMap、LinkedHashMap等实现类,帮助您更好地理解和应用Java Map。
【10月更文挑战第19天】深入剖析Java Map:不仅是高效存储键值对的数据结构,更是展现设计艺术的典范。本文从基本概念、设计艺术和使用技巧三个方面,详细解析HashMap、TreeMap、LinkedHashMap等实现类,帮助您更好地理解和应用Java Map。
40 3
|
23天前
|
存储 缓存 安全
在Java的Map家族中,HashMap和TreeMap各具特色
【10月更文挑战第19天】在Java的Map家族中,HashMap和TreeMap各具特色。HashMap基于哈希表实现,提供O(1)时间复杂度的高效操作,适合性能要求高的场景;TreeMap基于红黑树,提供O(log n)时间复杂度的有序操作,适合需要排序和范围查询的场景。两者在不同需求下各有优势,选择时需根据具体应用场景权衡。
27 2
|
23天前
|
存储 安全 Java
Java Map新玩法:深入探讨HashMap和TreeMap的高级特性
【10月更文挑战第19天】Java Map新玩法:深入探讨HashMap和TreeMap的高级特性,包括初始容量与加载因子的优化、高效的遍历方法、线程安全性处理以及TreeMap的自然排序、自定义排序、范围查询等功能,助你提升代码性能与灵活性。
23 2
|
1月前
|
Java
让星星⭐月亮告诉你,HashMap中保证红黑树根节点一定是对应链表头节点moveRootToFront()方法源码解读
当红黑树的根节点不是其对应链表的头节点时,通过调整指针的方式将其移动至链表头部。具体步骤包括:从链表中移除根节点,更新根节点及其前后节点的指针,确保根节点成为新的头节点,并保持链表结构的完整性。此过程在Java的`HashMap$TreeNode.moveRootToFront()`方法中实现,确保了高效的数据访问与管理。
29 2
|
1月前
|
Java 索引
让星星⭐月亮告诉你,HashMap之往红黑树添加元素-putTreeVal方法源码解读
本文详细解析了Java `HashMap` 中 `putTreeVal` 方法的源码,该方法用于在红黑树中添加元素。当数组索引位置已存在红黑树类型的元素时,会调用此方法。具体步骤包括:从根节点开始遍历红黑树,找到合适位置插入新元素,调整节点指针,保持红黑树平衡,并确保根节点是链表头节点。通过源码解析,帮助读者深入理解 `HashMap` 的内部实现机制。
33 2
|
1月前
|
算法 Java 容器
Map - HashSet & HashMap 源码解析
Map - HashSet & HashMap 源码解析
52 0
|
1月前
|
存储
让星星⭐月亮告诉你,HashMap的put方法源码解析及其中两种会触发扩容的场景(足够详尽,有问题欢迎指正~)
`HashMap`的`put`方法通过调用`putVal`实现,主要涉及两个场景下的扩容操作:1. 初始化时,链表数组的初始容量设为16,阈值设为12;2. 当存储的元素个数超过阈值时,链表数组的容量和阈值均翻倍。`putVal`方法处理键值对的插入,包括链表和红黑树的转换,确保高效的数据存取。
53 5
|
1月前
|
算法 索引
让星星⭐月亮告诉你,HashMap的resize()即扩容方法源码解读(已重新完善,如有不足之处,欢迎指正~)
`HashMap`的`resize()`方法主要用于数组扩容,包括初始化或加倍数组容量。该方法首先计算新的数组容量和扩容阈值,然后创建新数组。接着,旧数组中的数据根据`(e.hash & oldCap)`是否等于0被重新分配到新数组中,分为低位区和高位区两个链表,确保数据迁移时的正确性和高效性。
64 3