继承set接口的类有AbstractSet, ConcurrentSkipListSet, CopyOnWriteArraySet, EnumSet, HashSet, JobStateReasons, LinkedHashSet, TreeSet,接下来介绍其中几种。
HashSet此类实现 Set 接口,它不保证 set 的迭代顺序;特别是它不保证该顺序恒久不变。此类允许使用 null 元素。 jdk源码中有private transient HashMap<E,Object> map说明它其实是由HashMap实例支持。
LinkedHashSet具有可预知迭代顺序的 Set 接口的哈希表和链接列表实现。此实现与 HashSet 的不同之外在于,后者维护着一个运行于所有条目的双重链接列表。此链接列表定义了迭代顺序,即按照将元素插入到 set 中的顺序(插入顺序)进行迭代。注意,插入顺序不 受在 set 中重新插入的 元素的影响。此类提供所有可选的 Set 操作,并且允许 null 元素。与 HashSet 一样,它可以为基本操作(add、contains 和 remove)提供稳定的性能,假定哈希函数将元素正确地分布到存储段中。由于增加了维护链接列表的开支,其性能很可能会比 HashSet 稍逊一筹,不过,这一点例外:LinkedHashSet 迭代所需时间与 set 的大小 成正比,而与容量无关。HashSet 迭代很可能支出较大,因为它所需迭代时间与其容量 成正比。
TreeSet基于 TreeMap 的 NavigableSet 实现(jdk源码private transient NavigableMap<E,Object> m;)。使用元素的自然顺序对元素进行排序,或者根据创建 set 时提供的 Comparator 进行排序,具体取决于使用的构造方法。
以上几类基本方法一致,接下来看它们添加数据的效率:
public class Test_SetSpeed {
static long start = System.currentTimeMillis();
static long test(Set set) {
for(int i=0;i<500000;i++) {
set.add("a");
}
long end = System.currentTimeMillis()-start;
return end;
}
public static void main(String[] args) {
HashSet<String> hashSet = new HashSet<>();
LinkedHashSet<String> linkedHashSet = new LinkedHashSet<>();
TreeSet<String> treeSet = new TreeSet<>();
System.out.println("hashset"+test(hashSet));
System.out.println("linkedset"+test(linkedHashSet));
System.out.println("treeset"+test(treeSet));
}
}
输出:
hashset24
linkedset47
treeset90