java集合类(七)Set之LinkedHashSet&TreeSet

时间:2022-09-29 17:55:59

LinkedHashSet概述

  我们知道HashSet是无序的,那么LinkedHashSet从名称上我们就可以感觉到他和链表有关系,那么它是否是有序的呢?事实上,LinkedHashSet是具有可预知迭代顺序的Set接口的实现。此实现与HashSet的不同之处在于,它维护着一个运行于所有条目的双重链表。此链表定义了迭代顺序,该迭代顺序可为插入顺序或是访问顺序。
  还记得HashSet中有一个包访问权限的构造方法吗?它就是在LinkedHashSet应用到的。
  

LinkedHashSet声明与实现

public class LinkedHashSet<E>
extends HashSet<E>
implements Set<E>, Cloneable, java.io.Serializable {


public LinkedHashSet(int initialCapacity, float loadFactor) {
super(initialCapacity, loadFactor, true);
}

public LinkedHashSet(int initialCapacity) {
super(initialCapacity, .75f, true);
}

public LinkedHashSet() {
super(16, .75f, true);
}

public LinkedHashSet(Collection<? extends E> c) {
super(Math.max(2*c.size(), 11), .75f, true);
addAll(c);
}
}

从上面代码可以看出,LinkedHashSet继承自HashSet。它所有的构造方法调用的都是HashSet中那个只有包访问权限的构造方法。所以LinkedHashSet底层使用的是LinkedHashMap。它就是依靠LinkedHashMap的特性来实现自身所有功能。后续我们会详细介绍LinkedHashMap。明白了LinkedHashMapLinkedHashSet就是小菜一碟。

TreeSet概述

  TreeSet也是一个有序Set,并且我们可以定义元素在TreeSet中的顺序。实现方式就是在构造时,传入我们预先定义好的Comparator

TreeSet定义

public class TreeSet<E> extends AbstractSet<E>
implements NavigableSet<E>, Cloneable, java.io.Serializable

我们可以看到TreeSet实现了NavigableSet接口。Navigable是可驾驭的意思。实际上就是刚刚我说的可以指定TreeSet中元素排序。

TreeSet构造

  TreeSet(NavigableMap<E,Object> m) {
this.m = m;
}

public TreeSet() {
this(new TreeMap<E,Object>());
}

public TreeSet(Comparator<? super E> comparator) {
this(new TreeMap<>(comparator));
}

public TreeSet(Collection<? extends E> c) {
this();
addAll(c);
}

public TreeSet(SortedSet<E> s) {
this(s.comparator());
addAll(s);
}

我们可以看到默认的TreeSet构造方法实际上底层使用的是TreeMap进行存储。它就是依靠TreeMap的特性来实现自身功能。

TreeSet基本属性

    private transient NavigableMap<E,Object> m;

private static final Object PRESENT = new Object();

看下上面的属性,是否有点眼熟?在哪里见过。对就是在HashSet中。只不过当时的HashMap这里改成了NavigableMap。我们把TreeMap继承体系图拿出来看下:

java集合类(七)Set之LinkedHashSet&TreeSet

实际上TreeMap就是实现了NavigableMap接口,所以它具有NavigableMap的特性。所以想要彻底了解TreeSet,就需要研究TreeMap,有关TreeMap的内容我们后续会讲到。