从源码看区别:HashMap vs HashSet

55 阅读3分钟

HashMapHashSet 都是Java中常用的数据结构,它们主要用于存储和快速检索数据,但它们的用途和工作原理有所不同。

HashMap:

  1. 键值对存储HashMap用于存储“键-值对”,这意味着每个值(value)都可以通过一个唯一的键(key)访问。比如,你可以把HashMap想象成一个字典,每个单词(键)都有一个对应的定义(值)。

  2. 允许null值HashMap允许存储一个null键和多个null值。

  3. 无序存储HashMap不保证存储顺序,这意味着元素的顺序可能与插入顺序不同。

  4. 快速访问:由于使用哈希表的结构,HashMap能够提供快速的查找、插入和删除操作。

HashMap 示例

import java.util.HashMap;

public class HashMapExample {
    public static void main(String[] args) {
        // 创建一个HashMap实例
        HashMap<String, Integer> map = new HashMap<>();

        // 添加键值对
        map.put("Apple", 3);
        map.put("Banana", 2);
        map.put("Orange", 5);

        // 通过键获取值
        System.out.println("Apple: " + map.get("Apple")); // 输出: Apple: 3

        // 遍历键值对
        for (String key : map.keySet()) {
            System.out.println(key + ": " + map.get(key));
        }
    }
}

HashSet:

  1. 仅存储唯一元素HashSet仅存储不重复的元素,没有键值对的概念。你可以把它想象成一个存放独特项的集合。

  2. 基于HashMapHashSet实际上是基于HashMap实现的,在内部使用一个虚拟的对象作为值来维护元素的唯一性。

  3. 不允许重复HashSet不允许存储重复的元素。如果尝试添加重复的元素,它将不会覆盖现有的元素。

  4. 无序存储HashSet同样不保证元素的存储顺序。

HashSet 示例

import java.util.HashSet;

public class HashSetExample {
    public static void main(String[] args) {
        // 创建一个HashSet实例
        HashSet<String> set = new HashSet<>();

        // 添加元素
        set.add("Apple");
        set.add("Banana");
        set.add("Orange");
        set.add("Apple"); // 尝试添加重复元素

        // 显示HashSet中的元素
        for (String item : set) {
            System.out.println(item);
        }
        // 输出可能是: Apple, Banana, Orange
        // 注意:输出的顺序不一定是插入顺序,因为HashSet不保证顺序
    }
}

关键点

  • HashMap 展示了如何创建一个键值对映射,并通过键来获取值。
  • HashSet 展示了如何仅存储唯一元素,并自动忽略重复项。

讲解 HashMapHashSet 的源码实现可以帮助深入理解它们的区别和用途。以下是对它们的源码实现进行简要的说明和对比。

HashMap 源码解析

  1. 底层结构HashMap 是基于数组和链表(在JDK 8中,链表在一定条件下会转换为红黑树)实现的。它将键的哈希值用于确定存储位置。

  2. 节点存储:每个键值对被存储为一个 Node 对象,其中包含了键、值、哈希值和指向下一个节点的指针。

  3. 哈希函数HashMap 使用哈希函数来计算键的哈希值,用于决定元素在数组中的位置。

  4. 扩容机制:当元素数量超过一个阈值(默认负载因子为0.75)时,HashMap 会进行扩容,将容量扩大一倍,同时重新哈希现有元素。

HashSet 源码解析

  1. 基于HashMapHashSet 是通过一个 HashMap 实现的。它利用 HashMap 的键来存储集合中的元素,所有的值都指向同一个常量对象(通常是一个虚拟的 Object 实例)。

  2. 唯一性HashSet 依赖于 HashMap 的键的唯一性来保证不存储重复元素。

  3. 操作简单HashSet 的所有基本操作(如添加、删除、查询)都直接委托给内部的 HashMap 来完成。

源码对比

  • 结构HashMap 直接管理键值对,而 HashSet 通过 HashMap 来管理唯一元素。
  • 实现HashSet 是对 HashMap 的简化使用,主要利用其键的特性。
  • 存储内容HashMap 存储键值对,HashSet 仅存储唯一的键。

总的来说,HashMap适用于需要通过键快速访问值的场景,而HashSet适用于只需要快速访问和管理唯一元素的场景。选择使用哪种数据结构应根据具体需求来决定。