HashSet vs TreeSet vs LinkedHashSet
使用Set集合的主要原因是因为Set集合里面没有重复的元素。Set集合有三个常见的实现类:HashSet,TreeSet,LinkedHashSet。什么时候,选择哪一个使用非常重要。简单的说,如果你关注性能,应该使用HashSet;如果你需要一个有序的Set集合,应该使用TreeSet;如果你需要一个Set集合保存了原始的元素插入顺序,应该使用LinkedHashSet。
Set接口
Set接口继承Collection接口。Set集合不允许里面存在重复元素,每个元素都必须是唯一的。你只需要往Set集合简单的添加元素,重复元素会被自动移除。
HashSet,TreeSet,LinkedHashSet对比
HashSet是基于散列表实现的,元素没有顺序;add、remove、contains方法的时间复杂度为O(1)。
TreeSet是基于树实现的(红黑树),元素是有序的;add、remove、contains方法的时间复杂度为O(log (n))。因为元素是有序的,它提供了若干个相关方法如first(), last(), headSet(), tailSet()等;
LinkedHashSet介于HashSet和TreeSet之间,是基于哈希表和链表实现的,支持元素的插入顺序;基本方法的时间复杂度为O(1);
TreeSet例子
TreeSet<Integer> tree = new TreeSet<Integer>();
tree.add(12);
tree.add(63);
tree.add(34);
tree.add(45);
Iterator<Integer> iterator = tree.iterator();
System.out.print("Tree set data: ");
while (iterator.hasNext()) {
System.out.print(iterator.next() + " ");
}
结果输出:
Tree set data: 12 34 45 63
现在,我们换个元素类型,在进行插入,首先定义一个Dog类,如下
class Dog {
int size; public Dog(int s) {
size = s;
} public String toString() {
return size + "";
}
}
然后,往TreeSet添加若干个Dog对象,如下:
public class Q17 { public static void main(String[] args) {
TreeSet<Dog> dset = new TreeSet<Dog>();
dset.add(new Dog(2));
dset.add(new Dog(1));
dset.add(new Dog(3));
Iterator<Dog> iterator = dset.iterator();
while (iterator.hasNext()) {
System.out.print(iterator.next() + " ");
}
} }
以上代码,编译OK,但是运行时报错,如下:
Exception in thread "main" java.lang.ClassCastException: simplejava.Dog cannot be cast to java.lang.Comparable
at java.util.TreeMap.compare(TreeMap.java:1188)
at java.util.TreeMap.put(TreeMap.java:531)
at java.util.TreeSet.add(TreeSet.java:255)
at simplejava.Q17.main(Q17.java:22)
为什么呢?因为TreeSet是有序的,Dog类需要实现java.lang.Comparable接口的compareTo(),如下:
class Dog implements Comparable<Dog>{
int size; public Dog(int s) {
size = s;
} public String toString() {
return size + "";
} @Override
public int compareTo(Dog o) {
return size - o.size;
}
}
结果输出:
1 2 3
HashSet例子
HashSet<Dog> dset = new HashSet<Dog>();
dset.add(new Dog(2));
dset.add(new Dog(1));
dset.add(new Dog(3));
dset.add(new Dog(5));
dset.add(new Dog(4));
Iterator<Dog> iterator = dset.iterator();
while (iterator.hasNext()) {
System.out.print(iterator.next() + " ");
}
结果输出:
5 3 2 1 4
注意顺序是不确定的。
LinkedHashSet例子
LinkedHashSet<Dog> dset = new LinkedHashSet<Dog>();
dset.add(new Dog(2));
dset.add(new Dog(1));
dset.add(new Dog(3));
dset.add(new Dog(5));
dset.add(new Dog(4));
Iterator<Dog> iterator = dset.iterator();
while (iterator.hasNext()) {
System.out.print(iterator.next() + " ");
}
结果输出如下,保存了插入顺序:
2 1 3 5 4
性能测试
以下代码测试了这三个类add方法的性能:
Random r = new Random();
HashSet<Dog> hashSet = new HashSet<Dog>();
TreeSet<Dog> treeSet = new TreeSet<Dog>();
LinkedHashSet<Dog> linkedSet = new LinkedHashSet<Dog>();
// start time
long startTime = System.nanoTime();
for (int i = 0; i < 1000; i++) {
int x = r.nextInt(1000 - 10) + 10;
hashSet.add(new Dog(x));
}
// end time long endTime = System.nanoTime();
long duration = endTime - startTime;
System.out.println("HashSet: " + duration);
// start time
startTime = System.nanoTime();
for (int i = 0; i < 1000; i++) {
int x = r.nextInt(1000 - 10) + 10;
treeSet.add(new Dog(x));
}
// end time
endTime = System.nanoTime();
duration = endTime - startTime;
System.out.println("TreeSet: " + duration);
// start time
startTime = System.nanoTime();
for (int i = 0; i < 1000; i++) {
int x = r.nextInt(1000 - 10) + 10;
linkedSet.add(new Dog(x));
}
// end time
endTime = System.nanoTime();
duration = endTime - startTime;
System.out.println("LinkedHashSet: " + duration);
结果如下,我们可以发现,HashSet性能最好(注:以上代码我自己本地测试,HashSet不一定比LinkedHashSet快...)。
HashSet: 2244768
TreeSet: 3549314
LinkedHashSet: 2263320
这个测试并不是很精准,但是基本可以反映出TreeSet是性能最差的,因为需要排序。
相关阅读:ArrayList vs. LinkedList vs. Vector
译文链接:http://www.programcreek.com/2013/03/hashset-vs-treeset-vs-linkedhashset/
HashSet vs TreeSet vs LinkedHashSet的更多相关文章
- Java集合详解7:HashSet,TreeSet与LinkedHashSet
今天我们来探索一下HashSet,TreeSet与LinkedHashSet的基本原理与源码实现,由于这三个set都是基于之前文章的三个map进行实现的,所以推荐大家先看一下前面有关map的文章,结合 ...
- 【java提高】---HashSet 与TreeSet和LinkedHashSet的区别
HashSet 与TreeSet和LinkedHashSet的区别 今天项目开发,需要通过两个条件去查询数据库数据,同时只要满足一个条件就可以取出这个对象.所以通过取出的数据肯定会有重复,所以要去掉重 ...
- Java 容器 & 泛型:三、HashSet,TreeSet 和 LinkedHashSet比较
Writer:BYSocket(泥沙砖瓦浆木匠) 微博:BYSocket 豆瓣:BYSocket 上一篇总结了下ArrayList .LinkedList和Vector比较,今天泥瓦匠总结下Hash ...
- Java集合详解7:一文搞清楚HashSet,TreeSet与LinkedHashSet的异同
<Java集合详解系列>是我在完成夯实Java基础篇的系列博客后准备开始写的新系列. 这些文章将整理到我在GitHub上的<Java面试指南>仓库,更多精彩内容请到我的仓库里查 ...
- HashSet 与TreeSet和LinkedHashSet的区别
Set接口 Set不允许包含相同的元素,如果试图把两个相同元素加入同一个集合中,add方法返回false. Set判断两个对象相同不是使用==运算符,而是根据equals方法.也就 ...
- Set集合——HashSet、TreeSet、LinkedHashSet(2015年07月06日)
一.Set集合不同于List的是: Set不允许重复 Set是无序集合 Set没有下标索引,所以对Set的遍历要通过迭代器Iterator 二.HashSet 1.HashSet由一个哈希表支持,内部 ...
- HashSet,TreeSet和LinkedHashSet的区别
1. Set接口 Set不允许包含相同的元素,如果试图把两个相同元素加入同一个集合中,add方法返回false. Set判断两个对象相同不是使用==运算符,而是根据equals方法.也就是说,只要两个 ...
- java数据结构之HashSet和TreeSet以及LinkedHashSet
一.HashSet源码注释 public class HashSet<E> extends AbstractSet<E> implements Set<E>, Cl ...
- 【Java】常见的Set类型,HashSet、TreeSet、LinkedHashSet
HashSet,锋芒毕露,我们最常用到.其他两个,我们较少用到,今天,我们看看他们的区别. import java.util.HashSet; import java.util.Set; public ...
随机推荐
- asp.net获取站点根目录下子目录的名称
使用Visual Studio建立一个.aspx文件(Web Forms),例如hovertree.aspx,在页面上加入一个ListBox代码如下: <asp:ListBox runat=&q ...
- Redis系列三之持久化
一.Redis持久化 Redis是一个支持持久化的内存数据库,redis需要经常将内存中的数据同步到磁盘来保证持久化. redis提供了不同级别的持久化方法: Snapshotting(快照,默认方式 ...
- 组件Newtonsoft.Json实现object2json转换
很多情况下,我们需要把数据类型做一些转换,供其它外部的子系统调用. 最为典型的是生成json格式供javascript作调用. 现成的组件Newtonsoft.Json可以实现object2json之 ...
- 在吉日嘎拉DotNet.WebForm中使用FluentScheduler调度任务
有些用户一直说系统发送的邮件一直收不到,投诉系统不正常,这时候怎么洗刷冤屈呢?将发送的每一封Email都保存到数据库中,并记录发送的日志,让用户无话可说. 自己创建3个表: MessageFailed ...
- xamarin.ios 实现圆形进度条
using System; using UIKit; using System.Drawing; using CoreAnimation; namespace PMM { public class P ...
- ios 根据文字数量计算UILabel高度(已修改)
由于留言的朋友给出了更好的方法,所以下面的代码都是它留言中给出的,优于我前面计算Lable高度方法,这个可以说非常的准,是IOS自带的计算UILABEL高度的方式. 一.实现代码 // 创建label ...
- Thinkphp各种方法知识图谱
A方法:用于实例化控制器 ThinkPHP函数详解:A方法 B方法:执行某个行为 I方法(其命名来自于英文Input):获取输入参数 支持过滤和默认值 ThinkPHP函数详解:I方法 D方法:D函数 ...
- JavaScript concat() 方法-连接两个或多个数组
一,定义和用法 concat() 方法用于连接两个或多个数组. 该方法不会改变现有的数组,而仅仅会返回被连接数组的一个副本. 语法 arrayObject.concat(arrayX,arrayX,. ...
- arcgis engine 调用arcgis server服务
首先需要添加两个引用: using ESRI.ArcGIS.GISClient;using ESRI.ArcGIS.DataSourcesRaster; /// <summary> /// ...
- 解决Visual Stuido 2013中Xamarin的*.axml文件没有智能提示问题
最近发现VS2013开发Android,发现.axml无法进行智能提示. 1.打开VS2013菜单栏中,点击工具--选项--文本编辑器--文件扩展名 2.增加一个扩展名为"axml" ...