欢迎光临散文网 会员登陆 & 注册

java集合HashSet类

2022-07-24 09:20 作者:虚云幻仙  | 我要投稿

/**
* Set接口继承Collection接口 没有增加方法 set集合无序元素互异(equals()false)
* List接口继承Collection接口 增加了索引相关的方法 使容器有序可重复
* HashSet为Set接口的实现类 使用hash哈希/散列算法实现 允许有null元素 线程不安全
*/

public class TestHashSet {
   public static void main(String[] args) {
       Set<String> hs1 = new HashSet<>();
       //HashSet集合可以通过Set引用类型引用
       hs1.add("a");
       hs1.add("b");
       hs1.add("c");
       hs1.add("A");
       hs1.add("b");
       for (String e :
               hs1) {
           System.out.print(e+",");
       }
       //Set没有索引index 没有.get(index) 不能通过for(i)遍历
       //结果a,A,b,c,   Set集合无序 放入的顺序abcA和取出的顺序aAbc不同 Set集合互异 两个"b"只能存在一个

       System.out.println();
//        hs1.remove();hs1.clear();hs1.contains();hs1.size();hs1.toArray();等方法和List用法相同

       /*
       保持元素互异的大致原理为每增加一个元素时先.hashCode()计算该元素的hash值 再用hash值计算出元素应当保存在集合中的位置,如果当前位置没有元素则说明集合中没有与之重复的元素 之后完成添加
       如果当前位置存在元素则将进一步判断(&&短路与)指针是否相同/指向同一地址或者(||短路或)equals()相等 ture即判断为同一元素 不进行添加
       HashSet通过HashMap的哈希表和哈希桶存储元素 哈希表为存放哈希值的数组 每一个元素根据.hashCode()返回的哈希值存放于数组中对应的index
       哈希表数组中每一位都是一个哈希桶 哈希桶为单链表 保存表头结点 每一个元素通过index存放入链表中 当元素存放位置重复时新元素会添加到链表的表尾结点
        */

   }
}
class Element1{
   //自定义类测试HashSet集合的互异
   int id;
   String info;

   public Element1(int id, String info) {
       this.id = id;
       this.info = info;
   }

   @Override
   public String toString() {
       //generate自动生成toString的重写
       return "Element1{" +
               "id=" + id +
               ", info='" + info + '\'' +
               '}';
   }

   public static void main(String[] args) {
       Set<Element1> hs = new HashSet<>();
       //创建一个存放自定义类Element1对象的集合
       Element1 e1 = new Element1(1,"属性的值完全相同");
       Element1 e2 = new Element1(1,"属性的值完全相同");
       hs.add(e1);
       hs.add(e2);
       System.out.println(hs);
       //结果为[Element1{id=1, info='属性的值完全相同'}, Element1{id=1, info='属性的值完全相同'}]
       //两个内容完全相同的对象 因为.hashCode()值不同被判定为不同的元素

   }
}
class Element2{
   //更改类的.hashCode()方法 同时还需要更改.equals()方法 实现自定义对象的集合存储互异判定
   int id;
   String info;

   public Element2(int id, String info) {
       this.id = id;
       this.info = info;
   }
   //generate 自动生成equals() and hashCode()
   @Override
   public boolean equals(Object o) {
       System.out.println("哈希值相同才会执行equals");
       if (this == o) return true;
       //先判断指针是否相同
       if (o == null || getClass() != o.getClass()) return false;
       //判断形参o是否为空 以及this和o是否同类
       Element2 element2 = (Element2) o;
       //强转o
       return id == element2.id && Objects.equals(info, element2.info);
       //分别判断每个属性是否相同(&&短路与) info是对象,还需要调用对象.equals()判断
   }

   @Override
   public int hashCode() {
       System.out.println("先判断哈希值");
       return Objects.hash(id, info);
       //将id,info作为key/参数来计算哈希值 代替类对象的哈希值 这样当两个对象的id和info内容相同时计算出的哈希值相同
   }

   @Override
   public String toString() {
       return "Element2{" +
               "id=" + id +
               ", info='" + info + '\'' +
               '}';
   }

   public static void main(String[] args) {
       Set<Element2> hs = new HashSet<>();
       Element2 e1 = new Element2(1,"属性的值完全相同");
       Element2 e2 = new Element2(1,"属性的值完全相同");
       hs.add(e1);
       hs.add(e2);
       System.out.println(hs);
       /*结果为:
       先判断哈希值
       先判断哈希值
       哈希值相同才会执行equals
       [Element2{id=1, info='属性的值完全相同'}]
        */

       //每次add添加元素会计算哈希值 通过哈希值找index 存e1时index为空,不需要调用equals()直接存入元素 存e2时index存放了e1 哈希值会随元素一起存储,所以不需要第二次计算e1的哈希值
       //当index存在元素时才会执行equals 所以两次添加只在存e2时执行了一遍
       //通过哈希值和equals判断两个对象相同 只保留了e1 这样实现了通过属性判断互异

   }
}

java集合HashSet类的评论 (共 条)

分享到微博请遵守国家法律