Map - TreeSet & TreeMap 源码解析

130 阅读3分钟

在Java中,TreeSet 和 TreeMap 都是基于红黑树实现的集合类,它们分别实现了 Set 接口和 Map 接口。下面将对这两个类的源码进行解析,重点分析它们的底层实现、构造函数、get 和 put 方法(尽管 TreeSet 不直接实现 get 和 put 方法,但会讨论与之相关的操作)。

TreeSet 源码解析

1. 构造函数

TreeSet 提供了多种构造函数,但底层都调用了 TreeMap 的构造函数来初始化其内部的 NavigableMap。例如:

  • TreeSet():无参构造函数,使用默认的 TreeMap(自然排序)。
  • TreeSet(Collection<? extends E> c):通过集合构造,将集合中的元素添加到 TreeSet 中,使用默认的 TreeMap
  • TreeSet(Comparator<? super E> comparator):通过比较器构造,允许用户自定义排序规则。
2. 底层实现

TreeSet 的底层实际上是 TreeMap,其中 TreeSet 中的每个元素都存储在 TreeMap 的键(key)中,而值(value)则是一个固定的对象(通常是一个私有的静态常量,如 PRESENT),这个对象在 TreeSet 中不承载任何实际的信息,仅用于占位。

3. 添加元素

当向 TreeSet 添加元素时,实际上是调用 TreeMap 的 put 方法,将元素作为键,并将 PRESENT 作为值插入到 TreeMap 中。由于 TreeMap 的键是唯一的,因此可以确保 TreeSet 中的元素也是唯一的。

4. 排序

TreeSet 的排序规则取决于其内部 TreeMap 的排序规则。如果 TreeSet 是通过无参构造函数创建的,那么它将使用元素的自然排序(元素必须实现 Comparable 接口)。如果提供了比较器,那么将使用用户定义的排序规则。

TreeMap 源码解析

1. 构造函数

TreeMap 提供了两种主要的构造函数:

  • TreeMap():无参构造函数,使用元素的自然排序(元素必须实现 Comparable 接口)。
  • TreeMap(Comparator<? super K> comparator):带比较器的构造函数,允许用户自定义排序规则。
2. 底层实现

TreeMap 的底层是基于红黑树实现的,每个节点都是一个 Entry 对象,包含键(key)、值(value)、左子节点(left)、右子节点(right)、父节点(parent)以及节点的颜色(color,用于红黑树的平衡)。

3. 添加元素(put 方法)

put 方法是 TreeMap 的核心方法之一,用于向映射中添加键值对。在添加元素时,TreeMap 会根据排序规则找到新元素的正确位置,并插入到红黑树中。如果键已经存在,则更新其值(如果允许)。

4. 查找元素(get 方法)

get 方法用于根据键查找对应的值。在 TreeMap 中,这通常涉及到从根节点开始遍历红黑树,直到找到匹配的键或遍历完整个树。

总结

TreeSet 和 TreeMap 都是基于红黑树实现的集合类,它们提供了高效的排序和查找操作。TreeSet 通过将元素存储在 TreeMap 的键中来确保元素的唯一性和排序,而 TreeMap 则直接实现了 Map 接口,提供了基于键的映射和排序功能。两者在内部实现上紧密相关,但在使用上各有侧重。