当前位置:   article > 正文

TreeSet 、HashSet、LinkedHashSet的特点_treeset、hashset的特点

treeset、hashset的特点

不少大公司的面试题中会问TreeSet和HashSet有什么区别。此外LinkedHashSet也是Set的一种实现类,下面归纳的是三者的特点。

        HashSet是基于哈希表(Hash表)实现的,它不能保证线程安全,其中允许存在null元素,但null元素只能有1个。

        当程序员向HashSet中插入一个对象时, HashSet会调用该对象的hashCode()方法(如果该对象没定义,会调用Object)来得到该对象的hashCode值;然后会根据hashCode值来决定该对象在HashSet中的存放位置,如果遇到两个对象的hashCode值一致的情况则说明它们相等, HashSet同样不会允许插入重复的元素。

        上述描述包含了一层隐藏的含义, HashSet不能保证插入次序和遍历次序一致。

相比之下,LinkedHashSet同样是基于Hash表,它也是根据元素的hashCode值来决定元素的存储位置的,但是它同时也采用了链表的方式来保证插入次序和遍历次序一致。下面可LinketHashSetDemo.java例子看出两者的区别。

  1. import java.util.HashSet;
  2. import java.util.Iterator;
  3. import java.util.LinkedHashSet;
  4. import java.util.Set;
  5. public class LinkedHashSetDemo {
  6. public static void main(String[] args) {
  7. Set<String> strHashSet = new HashSet<String>();
  8. Set<String> strLinkedHashSet = new LinkedHashSet<String>();
  9. for(int i = 0; i<10; i++){
  10. strHashSet.add(String.valueOf(i));
  11. strLinkedHashSet.add(String.valueOf(i));
  12. }
  13. Iterator<String> setStringIt = strHashSet.iterator();
  14. while (setStringIt.hasNext())
  15. {
  16. System.out.print(setStringIt.next()+" ");
  17. }
  18. System.out.println();
  19. Iterator<String> linkedSetStringIt = strLinkedHashSet.iterator();
  20. while (linkedSetStringIt.hasNext())
  21. {
  22. System.out.print(linkedSetStringIt.next()+" ");
  23. }
  24. }
  25. }

        在main函数的第11- 14行中,通过for循环语句向两种集合中依次放入了1-10

        这10个String类型的对象,然后通过迭代器,在第17~21行中通过两个while循环分别按顺序输出它们的值,结果如下。

  1. 1 3 2 1 0 7 6 5 4 9 8
  2. 2 0 1 2 3 4 5 6 7 8 9

        第1行是针对HashSet的输出,从中可以看到它的遍历结果和插入的次序不一致;而,第2行是针对LinkedHashSet,输出次序和插入次序一致。

TreeSet是SortedSet接口的唯一实现类,它是用二叉树存储数据的方式来保证存储的元素处于有序状态,下面来看TreeSetDemo.java例子。

  1. import java.util.Iterator;
  2. import java.util.Set;
  3. import java.util.TreeSet;
  4. public class TreeSetDemo {
  5. public static void main(String[] args){
  6. Set<String> treeSet = new TreeSet<String>();
  7. treeSet.add("4");
  8. treeSet.add("3");
  9. treeSet.add("1");
  10. treeSet.add("2");
  11. Iterator<String> setStringIt = treeSet.iterator();
  12. while(setStringIt.hasNext()){
  13. System.out.print(setStringIt.next() + " ");
  14. }
  15. }
  16. }

        在第4行中,以泛型的方式创建了一个TreeSet,并从第6-9行,以无序的方式插入了4个String对象。注意, TreeSet不允许插入null值,所以运行第10行的代码时会有异常。

        当程序员在第14行通过迭代器遍历TreeSet对象时,会发现输出的次序和插入次序不一致,而且数据已经被排序,结果如下。

1 2 3 4 

        如果TreeSet中存储的不是上例中的基本数据类型,而是自定义的class,那么这个类必须实现Comparable接口中的compareTo方法, TreeSet会根据compareTo中的定义来区分大小,最终确定TreeSet中的次序。

        程序员可以在compareTo方法中定义排序依据。在前面的compareTo方法中,是以学生的id作为判断依据的,如果两个学生的id相等,那么这个方法的返回值是0,说明这两个学生是相等的(是同一个学生)。

        此外,该方法还可以返回1或-1,其中1表示大于,-1表示小于。下面通过SortedStudent.java例子来看TreeSet是如何对自定义类进行排序的。

  1. import java.util.Iterator;
  2. import java.util.Set;
  3. import java.util.TreeSet;
  4. class SortedStudent {
  5. private int id;
  6. public SortedStudent(int id) {this.id = id;}
  7. public int getId(){return id;}
  8. public boolean equals(SortedStudent stu)
  9. {
  10. if(stu.getId() == this.id)
  11. {
  12. return true;
  13. }
  14. else {
  15. return false;
  16. }
  17. }
  18. public int compareTO(Object obj){
  19. if(obj instanceof SortedStudent) {
  20. SortedStudent s = (SortedStudent) obj;
  21. if(s.getId() == this.getId())
  22. {
  23. return 0;
  24. }
  25. else{
  26. return s.getId()>this.getId()?-1:1;
  27. }
  28. }else{
  29. return 0;
  30. }
  31. }
  32. }
  33. public class SortStudentByID{
  34. public static void main(String[] args){
  35. SortedStudent s1 = new SortedStudent(1);
  36. SortedStudent s2 = new SortedStudent(2);
  37. SortedStudent s3 = new SortedStudent(3);
  38. SortedStudent s4 = new SortedStudent(4);
  39. Set<SortedStudent> stuSet = new TreeSet<SortedStudent>();
  40. stuSet.add(s2);
  41. stuSet.add(s4);
  42. stuSet.add(s1);
  43. stuSet.add(s3);
  44. Iterator<SortedStudent> itStu = stuSet.iterator();
  45. while(itStu.hasNext()){
  46. System.out.println(itStu.next().getId());
  47. }
  48. }
  49. }

在第2行定义的SortedStudent类的代码中,实现了Compareable接口。在第16行,程序员重写了compareTo方法,在这个方法中,如果两个学生对象的id相等,则认为它们相等,否则将用id的大小来判断大小。

在第38-41行中,虽然程序员用乱序的方式放入了4个学生对象,但TreeSet会自动地对它们进行排序,这可以从第46行的输出结果中得到验证。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/你好赵伟/article/detail/763563
推荐阅读
相关标签
  

闽ICP备14008679号