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