一文带你搞懂HashSet和TreeSet的区别!!!

291 阅读3分钟

在Java中,HashSetTreeSet是两种常用的Set集合实现,核心区别在于底层数据结构、元素顺序性和性能特性。本文将从以下几个方面进行详细的对比:

一、底层实现与数据结构

特性HashSetTreeSet
底层结构基于HashMap实现(哈希表)基于TreeMap实现(红黑树)
节点类型哈希桶(数组+链表/红黑树)平衡二叉搜索树(自平衡红黑树)
数据分布元素分散存储,哈希冲突时形成链表/树元素按排序规则组织为树结构

二、元素顺序性

特性HashSetTreeSet
顺序保证不保证顺序(插入顺序可能随机)自然排序自定义Comparator排序
遍历顺序无序(依赖哈希函数和扩容机制)按升序或定义的顺序遍历

三、性能对比

操作HashSetTreeSet
插入/删除O(1)(均摊时间,哈希冲突时可能退化)O(log n)(树的高度决定)
查找O(1)(哈希表直接定位)O(log n)(二分搜索树路径)
遍历O(n)(顺序不确定)O(n)(中序遍历,按排序顺序)

四、对元素的要求

特性HashSetTreeSet
哈希码要求必须正确实现hashCode()equals()无需hashCode(),但需可比较性
比较规则依赖equals()判断重复依赖compareTo()Comparator判断重复
Null支持允许存储null不允许null(除非自定义Comparator允许)

五、初始化与扩容

特性HashSetTreeSet
初始化参数初始容量(默认16)、负载因子(默认0.75)无需容量参数(树动态调整)
扩容机制容量翻倍(2倍),重新哈希所有元素无扩容,树结构自动平衡

六、适用场景

场景HashSetTreeSet
高频插入/删除优先选择(更快的时间复杂度)适用于需要排序的中等规模数据
快速查找适合基于哈希的快速访问适合范围查询(如查找大于某值的元素)
数据去重默认选择(无序去重)需要有序去重时使用

七、代码示例与注意事项

1. 自定义对象使用HashSet

必须正确覆盖hashCode()equals()

class Student {
    String id;
    String name;

    @Override
    public int hashCode() {
        return Objects.hash(id, name);
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) return true;
        if (obj == null || getClass() != obj.getClass()) return false;
        Student other = (Student) obj;
        return Objects.equals(id, other.id) && Objects.equals(name, other.name);
    }
}

// 使用示例
Set<Student> hashSet = new HashSet<>();
hashSet.add(new Student("001", "Alice"));

2. 自定义对象使用TreeSet

需实现Comparable或提供Comparator

class Product implements Comparable<Product> {
    String name;
    double price;

    @Override
    public int compareTo(Product other) {
        return Double.compare(this.price, other.price); // 按价格排序
    }
}

// 使用示例
Set<Product> treeSet = new TreeSet<>();
treeSet.add(new Product("Laptop", 999.99));

八、如何选择?

  • 选择HashSet
    需要快速插入、删除和查找,且不关心元素顺序;允许存储null;数据量大但无需排序。
  • 选择TreeSet
    需要元素按自然顺序或自定义顺序遍历;频繁执行范围查询(如subSet()tailSet());数据量中等且需要排序。

通过理解两者的底层实现和特性差异,可以根据实际需求选择最合适的集合实现,从而在性能和功能之间取得最佳平衡。

更多分享

  1. 一文带你吃透Android中常见的高效数据结构
  2. 详解:ArrayMap和SparseArray在HashMap上面的改进
  3. 详解:HashMap与TreeMap、HashTable的区别
  4. 详解:Set集合是如何保证元素不重复的
  5. 详解:LinkedHashMap的工作原理和实现