鱼C论坛

 找回密码
 立即注册
查看: 3117|回复: 0

[好文转载] HashSet vs. TreeSet vs. LinkedHashSet

[复制链接]
发表于 2017-5-8 11:26:10 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
本帖最后由 零度非安全 于 2017-5-8 11:25 编辑
本文由 ImportNew - 唐小娟 翻译自 Programcreek。
原文出处:Programcreek
原文链接:http://www.programcreek.com/2013 ... t-vs-linkedhashset/

Set 集合不包含重复的元素,这是使用 Set 的主要原因。有三种常见的 Set 实现 —— HashSet,TreeSet 和 LinkedHash

Set。什么时候使用它们,使用哪个是个重要的问题。总体而言,如果你需要一个访问快速的 Set,你应该使用 HashSet;

当你需要一个排序的 Set,你应该使用 TreeSet;当你需要记录下插入时的顺序时,你应该使用 LinedHashSet。

1. Set 接口

Set 接口继承了 Collection 接口。Set 集合中不能包含重复的元素,每个元素必须是唯一的。你只需将元素加入 set 中,重

复的元素会自动移除。

collection.jpeg

2. HashSet vs. TreeSet vs. LinkedHashSet

HashSet 是采用 hash 表来实现的。其中的元素没有按顺序排列,add()、remove() 以及 contains() 等方法都是复杂度为

O(1) 的方法。

TreeSet 是采用树结构实现(红黑树算法)。元素是按顺序进行排列,但是 add()、remove() 以及 contains() 等方法都是复

杂度为 O(log (n)) 的方法。它还提供了一些方法来处理排序的 set,如 first(), last(), headSet(),tailSet() 等等。

LinkedHashSet 介于 HashSet 和 TreeSet 之间。它也是一个 hash 表,但是同时维护了一个双链表来记录插入的顺序。基

本方法的复杂度为 O(1)。

3. TreeSet的例子
  1. TreeSet tree = new TreeSet();
  2. tree.add(12);
  3. tree.add(63);
  4. tree.add(34);
  5. tree.add(45);
  6. //用Collection中的iterator()方法获取该集合对象的迭代器
  7. Iterator iterator = tree.iterator();
  8. System.out.print("Tree set data:");
  9. while(iterator.hasNext()){
  10.     System.out.print(iterator.next() + " ");
  11. }
复制代码

输出如下:
  1. Tree set data: 12 34 45 63
复制代码

现在让我们定义一个 Dog 类:
  1. class Dog {
  2.     int size;       
  3.     public Dog(int s){
  4.         size = s;
  5.     }       
  6.     public String toString(){
  7.         return size + "";
  8.     }       
  9. }
复制代码

我们将“dog”添加到 TreeSet 中:
  1. import java.util.Iterator;
  2. import java.util.TreeSet;

  3. public class TestTreeSet {
  4.     public static void main(String[] args) {
  5.         TreeSet dset = new TreeSet();
  6.         dset.add(new Dog(2));
  7.         dset.add(new Dog(1));
  8.         dset.add(new Dog(3));

  9.         Iterator iterator = dset.iterator();

  10.         while (iterator.hasNext()) {
  11.             System.out.print(iterator.next() + " ");
  12.         }
  13.     }
  14. }
复制代码

编译正常,但是运行时出错:
  1. Exception in thread "main" java.lang.ClassCastException: collection.Dog cannot be cast to java.lang.Comparable
  2.     at java.util.TreeMap.put(Unknown Source)
  3.     at java.util.TreeSet.add(Unknown Source)
  4.     at collection.TestTreeSet.main(TestTreeSet.java:22)
复制代码

因为 TreeSet 是有序的,Dog 类必须实现 java.lang.Comparable 的 compareTo() 方法才行:
  1. class Dog implements Comparable{
  2.     int size;
  3.     public Dog(int s) {
  4.         size = s;
  5.     }
  6.     public String toString() {
  7.         return size + "";
  8.     }
  9.     @Override
  10.     public int compareTo(Dog o) {
  11.         return size - o.size;
  12.     }
  13. }
复制代码

输出:
  1. 1 2 3
复制代码

4. HashSet 的例子
  1. HashSet dset = new HashSet();
  2. dset.add(new Dog(2));
  3. dset.add(new Dog(1));
  4. dset.add(new Dog(3));
  5. dset.add(new Dog(5));
  6. dset.add(new Dog(4));
  7. Iterator iterator = dset.iterator();
  8. while (iterator.hasNext()) {
  9.     System.out.print(iterator.next() + " ");
  10. }
复制代码

输出:
  1. 5 3 2 1 4
复制代码

注意输出顺序是不确定的。

5. LinkedHashSet 的例子
  1. LinkedHashSet dset = new LinkedHashSet();
  2. dset.add(new Dog(2));
  3. dset.add(new Dog(1));
  4. dset.add(new Dog(3));
  5. dset.add(new Dog(5));
  6. dset.add(new Dog(4));
  7. Iterator iterator = dset.iterator();
  8. while (iterator.hasNext()) {
  9.     System.out.print(iterator.next() + " ");
  10. }
复制代码

输出的顺序时确定的,就是插入的顺序。

6. 性能测试

下面的代码测试了以上三个类的add()方法的性能。
  1. public static void main(String[] args) {

  2.     Random r = new Random();

  3.     HashSet<Dog> hashSet = new HashSet<Dog>();
  4.     TreeSet<Dog> treeSet = new TreeSet<Dog>();
  5.     LinkedHashSet<Dog> linkedSet = new LinkedHashSet<Dog>();

  6.     // start time
  7.     long startTime = System.nanoTime();

  8.     for (int i = 0; i < 1000; i++) {
  9.         int x = r.nextInt(1000 - 10) + 10;
  10.         hashSet.add(new Dog(x));
  11.     }
  12.     // end time
  13.     long endTime = System.nanoTime();
  14.     long duration = endTime - startTime;
  15.     System.out.println("HashSet: " + duration);

  16.     // start time
  17.     startTime = System.nanoTime();
  18.     for (int i = 0; i < 1000; i++) {
  19.         int x = r.nextInt(1000 - 10) + 10;
  20.         treeSet.add(new Dog(x));
  21.     }
  22.     // end time
  23.     endTime = System.nanoTime();
  24.     duration = endTime - startTime;
  25.     System.out.println("TreeSet: " + duration);

  26.     // start time
  27.     startTime = System.nanoTime();
  28.     for (int i = 0; i < 1000; i++) {
  29.         int x = r.nextInt(1000 - 10) + 10;
  30.         linkedSet.add(new Dog(x));
  31.     }
  32.     // end time
  33.     endTime = System.nanoTime();
  34.     duration = endTime - startTime;
  35.     System.out.println("LinkedHashSet: " + duration);

  36. }
复制代码

从输出看来,HashSet是最快的:
  1. HashSet: 2244768
  2. TreeSet: 3549314
  3. LinkedHashSet: 2263320
复制代码

这个测试并不是非常精确,但足以反映基本的情况。
hashset-treeset-linkedhashset1.png



想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-4-20 03:00

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表