Java 之 HashSet与TreeSet
HashSet
此类实现 Set 接口,由哈希表(实际上是一个 HashMap 实例)支持。它不保证 set 的迭代顺序;特别是它不保证该顺序恒久不变。此类允许使用 null 元素。
TreeSet
底层数据结构是红黑树(是一个自平衡的二叉树)
基于 TreeMap 的 NavigableSet 实现。使用元素的自然顺序对元素进行排序,或者根据创建 set 时提供的 Comparator 进行排序,具体取决于使用的构造方法。
注意,如果要正确实现 Set 接口,则 set 维护的顺序(无论是否提供了显式比较器)必须与 equals 一致。(关于与 equals 一致 的精确定义,请参阅 Comparable 或 Comparator。)这是因为 Set 接口是按照 equals 操作定义的,但 TreeSet 实例使用它的 compareTo(或 compare)方法对所有元素进行比较,因此从 set 的观点来看,此方法认为相等的两个元素就是相等的。即使 set 的顺序与 equals 不一致,其行为也是 定义良好的;它只是违背了 Set 接口的常规协定。
注意,此实现不是同步的。如果多个线程同时访问一个 TreeSet,而其中至少一个线程修改了该 set,那么它必须 外部同步。这一般是通过对自然封装该 set 的对象执行同步操作来完成的。如果不存在这样的对象,则应该使用 Collections.synchronizedSortedSet 方法来“包装”该 set。此操作最好在创建时进行,以防止对 set 的意外非同步访问
栗子
package com.hk.spring.set;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Random;
import java.util.Set;
import java.util.TreeSet;
import org.junit.Test;
/**
* 随机产生十个20以内不重复的整数
* @author 浪丶荡
*
*/
public class SetDemo {
private Random random = new Random();
@Test
public void HashSetTest(){
Random random = new Random();
HashSet<Integer> hashSet = new HashSet<Integer>();
while(hashSet.size()<10){
hashSet.add(random.nextInt(20)+1);
}
System.out.println("HashSet 实现");
print(hashSet);
}
private void print(Set<Integer> set) {
for (Iterator iterator = set.iterator(); iterator.hasNext();) {
Integer integer = (Integer) iterator.next();
System.out.print(integer+"\t");
}
System.out.println("\n");
}
@Test
public void TreeSetTest(){
TreeSet<Integer> treeSet = new TreeSet<Integer>();
while(treeSet.size()<10){
treeSet.add(random.nextInt(20)+1);
}
System.out.println("TreeSet 实现");
print(treeSet);
}
}
结果
TreeSet 实现
2 3 5 7 9 12 13 16 17 20
HashSet 实现
17 19 18 3 6 8 9 12 13 14
总结:HashSet与TreeSet异同
一、都是Set接口的实现类,所以元素都是唯一的
二、Java API 上说HashSet底层数据结构是哈希表(实际上是一个 HashMap 实例)
从它的add方法的实现就可以看出

三、HashSet的元素是无序的
四、TreeSet底层数据结构是红黑树
五、TreeSet的元素是有序的
六、使用元素的自然顺序对元素进行排序,或者根据创建 set 时提供的 Comparator 进行排序,具体取决于使用的构造方法。 当是无参构造函数就是自然排序,当构造函数的参数是Comparator ,就按Comparator 指定的排序方式排序