java collectionjava 设计

HashSet、TreeSet、LinkedHashSet

2017-08-20  本文已影响31人  Arya鑫

Set几乎都是内部用一个Map来实现, 因为Map里的KeySet就是一个Set,而value是假值,全部使用同一个Object。Set的特征也继承了那些内部Map实现的特征。


HashSet

只去重复,没有顺序,不是同步,可存储null,只能我存储一个null。

HashSet的add方法会调用hashCode和equals, 所以如果要把一个对象放入HashSet中,重写该对象对应类的equals方法,也应该重写其hashCode()方法。其规则是如果两个对 象通过equals方法比较返回true时,其hashCode也应该相同。另外,对象中用作equals比较标准的属性,都应该用来计算 hashCode的值。

如果我们希望一个集合有去重复的功能, 可以在它的add方法中检查要添加的对象在集合中是否存在. 迭代集合中每个元素, 和要添加的比较, 如果相同, 就不存. 如果使用上述方法, 当集合元素特别多的时候, 效率会很低.例如: 集合中有1万个元素, 当存储下一个的时候, 需要和前面1万个都比较, 效率较低。工作原理:

每次存储对象的时候, 调用对象的hashCode()方法, 计算一个哈希值. 在集合中查找是否包含哈希值相同的元素。

如果没有哈希值相同元素, 直接存入。

如果有哈希值相同的元素, 逐个使用equals()方法比较。

比较结果全为false就存入。

如果比较结果有true则不存。

如何将自定义类对象存入HashSet进行去重复。

类中必须重写hashCode()方法和equals()方法。

equals()方法中比较所有属性。

hashCode()方法要保证属性相同的对象返回值相同, 属性不同的对象尽量不同。


LinkedHashSet

HashSet的子类, 去重复, 并且保留存储顺序

LinkedHashSet在迭代访问Set中的全部元素时,性能比HashSet好,但是插入时性能稍微逊色于HashSet。



TreeSet

去重复, 并且可以按照某种顺序排序

TreeSet的add方法会将对象转为Comparable, 然后调用compareTo方法, 所以存储在TreeSet中的对象必须实现Comparable, 重写compareTo方法。TreeSet支持两种排序方式,自然排序 和定制排序。

(http://www.jianshu.com/p/38a255477b08)

TreeSet存储对象的时候, 可以排序, 但是需要指定排序的算法

Integer能排序(有默认顺序), String能排序(有默认顺序), 自定义的类存储的时候出现异常(没有顺序)

 如果想把自定义类的对象存入TreeSet进行排序, 那么必须实现Comparable接口

在类上implement Comparable

重写compareTo()方法

在方法内定义比较算法, 根据大小关系, 返回正数负数或零

在使用TreeSet存储对象的时候, add()方法内部就会自动调用compareTo()方法进行比较, 根据比较结果使用二叉树形式进行存储


区别总结:

一.HashSet

特点:

1.HashSet中不能有相同的元素,可以有一个Null元素,存入的元素是无序的。

2.HashSet如何保证唯一性?

1).HashSet底层数据结构是哈希表,哈希表就是存储唯一系列的表,而哈希值是由对象的hashCode()方法生成。

2).确保唯一性的两个方法:hashCode()和equals()方法。

3.添加、删除操作时间复杂度都是O(1)。

4.非线程安全

二.LinkedHashSet

特点:

1.LinkedHashSet中不能有相同元素,可以有一个Null元素,元素严格按照放入的顺序排列。

2.LinkedHashSet如何保证有序和唯一性?

1).底层数据结构由哈希表和链表组成。

2).链表保证了元素的有序即存储和取出一致,哈希表保证了元素的唯一性。

3.添加、删除操作时间复杂度都是O(1)。

4.非线程安全

三.TreeSet

特点:

1.TreeSet是中不能有相同元素,不可以有Null元素,根据元素的自然顺序进行排序。

2.TreeSet如何保证元素的排序和唯一性?

底层的数据结构是红黑树(一种自平衡二叉查找树)

3.添加、删除操作时间复杂度都是O(log(n))

4.非线程安全

四.总结:

通过以上特点可以分析出,三者都保证了元素的唯一性,如果无排序要求可以选用HashSet;如果想取出元素的顺序和放入元素的顺序相同,那么可以选用LinkedHashSet。如果想插入、删除立即排序或者按照一定规则排序可以选用TreeSet。

如果你想访问set中的任意元素,无疑TreeSet是最快的,因为TreeSet已经排序好了无需再遍历整个数组或者是链表。所有的linked实现的结构在访问任意元素傻上都很慢,但是在移动和替换元素上是很快的。

HashSet是大多内存要求的,如果你有大量的RAM,并且在你的set中的读写的性能相对合理的话,那么HashSet是个不错的选择。



http://blog.csdn.net/zhangwenjun32/article/details/8745431

http://blog.csdn.net/maoyeqiu/article/details/48766135

http://blog.csdn.net/u013256816/article/details/50917379

http://blog.csdn.net/stemq/article/details/66477615

http://blog.csdn.net/stemq/article/details/66477615


上一篇下一篇

猜你喜欢

热点阅读