带你了解一下集合HashSet

1 HashSet概述

特点:作为Set集合的一种,首先是无序的,不可重复的;允许存放null值;底层封装HashMap;实现是不同步的,线程不安全;

常用构造:

public HashSet() :构造一个新的空 set,其底层 HashMap 实例的默认初始容量是 16,加载因子是 0.75。

常用方法:

1)添加功能
boolean add(E e) : 如果此 set 中尚未包含指定元素,则添加指定元素
2)判断功能
boolean isEmpty(): 如果此 set 不包含任何元素,则返回 true。
boolean contains(Object o): 如果此列表中包含指定的元素,则返回 true
3)获取功能
int size() : 返回此 set 中的元素的数量(set 的容量)。
4)删除功能
void clear() :移除此列表中的所有元素。注意:此方法比较暴力,一般不使用。
boolean remove(Object o):如果指定元素存在于此 set 中,则将其移除。
5)迭代器功能
public Iteratoriterator() 返回对此 set 中元素进行迭代的迭代器。返回元素的顺序并不是特定的。

2 HashSet的使用

1)使用HashSet存储字符串:如何实现存储元素的唯一性??
  1. packageSetTest;
  2. import java.util.HashSet;
  3. import java.util.Set;
  4. publicclassHashSetDemo1{
  5.   publicstaticvoid main(String[] args){
  6.     Set<String>set=newHashSet<String>();
  7.     set.add(“java”);
  8.     set.add(“js”);
  9.     set.add(“sql”);
  10.     set.add(“java”);
  11.     set.add(“js”);
  12.     set.add(“jquery”);
  13.     for(String s:set){
  14.       System.out.println(s);
  15.     }
  16.   }
  17. }

输出结果:

  1. java
  2. js
  3. jquery
  4. sql

分析:

1)通过查看add()方法的源码,底层是使用HashMap的put()方法实现元素的存取,继续查看put存储元素的源码,可知要保证存储元素的唯一性依赖于元素的equals和hashCode方法的实现,首先看hashCode方法,如果存在hash值和待存储元素的hash值相等的元素,则继续通过equals方法比较二者。如果相等则不存储。
2)由于String类重写了equals()和hashCode()方法: 这两个方法都是依赖于String对象的内容》》只有字符串内容一样就认为是相等的,不会在集合中存储。
  1. publicint hashCode(){
  2.   int h = hash;
  3.   if(h ==0&& value.length >0){
  4.     char val[]= value;
  5.     for(int i =0; i < value.length; i++){
  6.       h =31* h + val[i];//hash值的生成依赖于字符串的内容
  7.     }
  8.     hash = h;
  9.   }
  10.   return h;
  11. }
  12. publicboolean equals(Object anObject){
  13.   if(this== anObject){
  14.     returntrue;
  15.   }
  16.   if(anObject instanceofString){
  17.     String anotherString =(String)anObject;
  18.     int n = value.length;
  19.     if(n == anotherString.value.length){
  20.       char v1[]= value;
  21.       char v2[]= anotherString.value;
  22.       int i =0;
  23.       while(n–!=0){//判断两个字符串是否相等,依赖于字符串的内容是否一样
  24.         if(v1[i]!= v2[i])
  25.           returnfalse;
  26.         i++;
  27.       }
  28.       returntrue;
  29.     }
  30.   }
  31.   returnfalse;
  32. }
同样在存储其他基本类型的装箱类型也可以实现存储元素的唯一性,因为这些装箱类型也实现了equals()和hashCode()方法。(如Integer,Character等)
2)使用HashSet存储自定义对象:如何保证存储元素的唯一性(此处我们认为Student的name和age相等就意味着元素相等)
  1. packageSetTest;
  2. publicclassStudent{
  3.   privateString name;
  4.   privateint age;
  5.   publicStudent(String name,int age){
  6.     this.name = name;
  7.     this.age = age;
  8.   }
  9.   publicString getName(){
  10.     return name;
  11.   }
  12.   publicvoid setName(String name){
  13.     this.name = name;
  14.   }
  15.   publicint getAge(){
  16.     return age;
  17.   }
  18.   publicvoid setAge(int age){
  19.     this.age = age;
  20.   }
  21.   @Override
  22.   publicString toString(){
  23.     return”Student [name=”+ name +”, age=”+ age +”]”;
  24.   }
  25.   @Override
  26.   publicint hashCode(){
  27.     int hash = name.hashCode()+age;
  28.     return hash;
  29.   }
  30.   @Override
  31.   publicboolean equals(Object obj){
  32.     if(this==obj)
  33.       returntrue;
  34.     if(obj instanceofStudent){
  35.       Student stu =(Student)obj;
  36.       if(stu.getName().equals(name)&& stu.getAge()==age)
  37.         returntrue;
  38.     }
  39.     returnfalse;
  40.   }
  41. }
  1. packageSetTest;
  2. import java.util.HashSet;
  3. import java.util.Set;
  4. publicclassHashSetTest{
  5.   publicstaticvoid main(String[] args){
  6.     Set<Student>set=newHashSet<Student>();
  7.     Student stu1 =newStudent(“hu”,12);
  8.     Student stu2 =newStudent(“wen”,27);
  9.     Student stu3 =newStudent(“rt”,12);
  10.     Student stu4 =newStudent(“you”,15);
  11.     Student stu5 =newStudent(“hu”,12);
  12.     Student stu6 =newStudent(“te”,17);
  13.     Student stu7 =newStudent(“wen”,27);
  14.     set.add(stu1);
  15.     set.add(stu2);
  16.     set.add(stu3);
  17.     set.add(stu4);
  18.     set.add(stu5);
  19.     set.add(stu6);
  20.     set.add(stu7);
  21.     for(Student s:set){
  22.       System.out.println(s.getName()+”——“+s.getAge());
  23.     }
  24.   }
  25. }
输出结果:
  1. te——17
  2. hu——12
  3. wen——27
  4. rt——12
  5. you——15

分析:

从输出结果可知,此集合的存储保证了元素的唯一性,主要是因为我们在自定义类中重写了equals和hashCode方法。

总结:

要想在hashSet集合中实现元素存取的唯一性,由于底层判断依赖于equals和hashCode方法,故所存取的元素需要重写这两个方法,以按照我们的期待存取元素。保证元素唯一性。

重新强调下:

hashCode和equals方法的使用概念非常重要:不仅可以用于set还可以用于map。1)使用java系统类,如String/Date/或者数字包装类(Integer/Float),不必重写hashCode和equals方法。2)如果要在set或者map中添加自定义类的实例,就要确保equals和hashCode方法能正常工作,否则代码可能出现无法预料的结果

HashSet和其子类LinkedHashSet的区别:

简单的例子:
  1. HashSet<Student> set1 =newHashSet<Student>();
  2. Student stu1 =newStudent(“wen”,12);
  3. Student stu2 =newStudent(“di”,15);
  4. Student stu3 =newStudent(“wu”,13);
  5. Student stu4 =newStudent(“yy”,14);
  6. Student stu5 =newStudent(“fr”,16);
  7. Student stu6 =newStudent(“vc”,11);
  8. Student stu7 =newStudent(“aw”,10);
  9. set1.add(stu1);
  10. set1.add(stu2);
  11. set1.add(stu3);
  12. set1.add(stu4);
  13. set1.add(stu5);
  14. set1.add(stu6);
  15. set1.add(stu7);
  16. System.out.println(“—————–HashSet———————-“);
  17. for(Student stu:set1){
  18.   System.out.println(stu.getName()+”———–“+stu.getAge());
  19. }
  20. System.out.println(“—————–LinkedHashSet———————-“);
  21. LinkedHashSet<Student> set2 =newLinkedHashSet<Student>();
  22. set2.add(stu1);
  23. set2.add(stu2);
  24. set2.add(stu3);
  25. set2.add(stu4);
  26. set2.add(stu5);
  27. set2.add(stu6);
  28. set2.add(stu7);
  29. for(Student stu:set2){
  30.   System.out.println(stu.getName()+”———–“+stu.getAge());
  31. }
输出结果是:
  1. —————–HashSet———————-
  2. wu———–13
  3. yy———–14
  4. vc———–11
  5. wen———–12
  6. di———–15
  7. fr———–16
  8. aw———–10
  9. —————–LinkedHashSet———————-
  10. wen———–12
  11. di———–15
  12. wu———–13
  13. yy———–14
  14. fr———–16
  15. vc———–11
  16. aw———–10
LinkedHashSet的功能与HashSet类似,毕竟是其子类。
有一个重要的区别:LinkedHashSet返回的元素顺序是可以预测的,即元素添加到集合的顺序。该功能可以用来快速查找并判断集合中是否包含指定对象,或者用于检索元素并按照元素的添加顺序返回元素。
本站所有文章均由网友分享,仅用于参考学习用,请勿直接转载,如有侵权,请联系网站客服删除相关文章。若由于商用引起版权纠纷,一切责任均由使用者承担
极客文库 » 带你了解一下集合HashSet

Leave a Reply