java基础:浅谈HashSet的使用

Set

set类似于一个罐子,程序可以把多个对象全部丢到罐子中,从表面上看,Set和Collection的用法差不多,但是Set有着自己的特点:

元素无序,不能添加重复元素

HashSet

1.简介:

HashSet是Set接口的典型实现,拥有着以下特点:

*不能保证元素的排列顺序,添加顺序和输出顺序可能不同

*HashSet不是同步的,如果多个线程同时访问一个HashSet,假设多个线程同时修改集合时,需要通过代码来进行同步

*集合元素值可能是null

 

2.使用事项

由于HashSet是不能添加重复元素的,如何判断元素是否相同呢?

HashSet会调用hashCode方法先计算出hashCode对象值从而知晓该元素在HashSet中的位置,同时调用equals方法(返回boolean)进行判断两个对象是否一致

下面先举一个栗子:

import java.util.HashSet;

public class Demo1 {
    //测试HashSet的性质
    //无序,不能出现重复的elem

    /**
     * 在HashSet中如何判断元素是否相同 1.HashCode一致 2.equals返回true
     */
    //重写equals方法
    static class A {
        @Override
        public boolean equals(Object obj) {
            return true;
        }
    }

    static class B {
        @Override
        public int hashCode() {
            return 1;
        }
    }

    static class C {
        @Override
        public int hashCode() {
            return 2;
        }

        @Override
        public boolean equals(Object obj) {
            return true;
        }
    }

    //测试添加类的情况
    public static void main(String[] args) {
        HashSet books = new HashSet();
        books.add(new A());
        books.add(new A());

        books.add(new B());
        books.add(new B());
        books.add(new C());
        books.add(new C());
        System.out.println(books);
        //
        /**
         * 

    }
}

总结一下:
结论:出现了两个A 两个B 一个C
          *说明只有当equals和HashCode都相同的时候  才证明在HashSet中为相同的元素
         *在HashSet中一旦遇见相同的元素,add()方法返回false 直接不加入(HashSet中无法加入相同的元素)
         * HashSet规则:如果两个对象通过equals的方法比较返回true,则这两个对象的hashCode值也应该相同
         * 当把对象加入HashSet中,如果需要重写该对象对应的类的equals()方法,则也应该重写其hashCode()方法
         * 如果两个对象的equals相同,但是hashCode不同,所以两个对象会根据HashCode放在Hash表的不同位置,从而使得两个对象都可以添加成功,但是和规则相悖
         * 如果两个对象的hashCode相同 但是.equals()方法返回false,所以只能使用一种链式结构来保存对象,所以当一个HashSet中两个以上的元素具有相同的hashCode值 会导致性能下降

 

3.具体说明:

上述为了证明hashSet的性质,重写了hashCode方法和equals方法,但是,其实重写这些方法也要遵循一定的原则

*程序运行时,同一个对象多次调用hashCode方法时应该返回相同的值

*当两个对象通过equals()方法返回true时,两个对象的hashCode()方法应该也返回相同的值

 

注:如何计算hashCode()?

1.单独的实例变量计算

2.然后将计算出的多个hashCode值进行组合计算出一个总的hashCode值

 

demo:(参考:https://www.cnblogs.com/zhshlimi/p/8471752.html

@Override
    public int hashCode() {
        //设置初始值
        int result = 17;

        //假设有效域为: name,age,idCardNo,incomeAnnual,sex,brithDay
        int c = 0;
        //计算name (String为对象类型,他的计算直接调用本身的hashCode)
        c = name.hashCode();
        result = result * 37 + c;

        //计算age (int/byte/char/short类型,他的计算直接调用本身的值)
        c = this.getAge();
        result = result * 37 + c;

        //计算idCardNo (long类型,他的计算 (int)(field^(field >>> 32)) 无符号右移32位)
        c = (int) (this.idCardNo ^ (this.idCardNo >>> 32));
        result = result * 37 + c;

        //计算 incomeAnnual (double类型,他的计算 Double.doubleToLongBits(field)后,再按Long类型计算 )
        //(float类型,他的计算 Float.floatToIntBits(field)  )
        long tmp = Double.doubleToLongBits(this.incomeAnnual);
        c = (int) (tmp ^ (tmp >>> 32));
        result = result * 37 + c;

        //计算 sex (sex为boolean类型,他的计算直接调用 c=sex?1:0)
        c = this.isSex() ? 1 : 0;
        result = result * 37 + c;

        //计算 brithDay (brithDay为Date对象类型,他的计算直接调用 本身的hashCode)
        c = this.getBirthDay().hashCode();
        result = result * 37 + c;

        return result;
    }


        
 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值