Java中hashset底层实现机制

今天写算法,遇到了这个问题:

HashSet<int[]> hs = new HashSet<>();
int[] arr1 = {4,5};
int[] arr2 = {4,5};
hs.add(arr1);
hs.add(arr2);
System.out.println(hs.size());

结果为:2

HashSet<ArrayList<Integer>> hs = new HashSet<>();
ArrayList<Integer> arr1 = new ArrayList<>(){{add(4);add(5)}};
ArrayList<Integer> arr2 = new ArrayList<>(){{add(4);add(5)}};
hs.add(arr1);
hs.add(arr2);
System.out.prinln(hs.size());

输出为:1

原因:

HashSet的底层是用hashmap实现的,用到了对象的equals方法和hashcode值
例如,当要add一个新对象时,先计算他的hashcode值,根据hashcode值,插入到hashmap合适的位置中,

如果位置上有元素,则采用equals方法比较,如果相同不插入,如果不相同,新找一个位置插入
如果位置上没有元素,则直接插入。

因此,当插入新元素时,如果这个元素和已存中的某一个元素(any)的hashcode相同且equals()返回为真,那么就不能插入

备注:除非你重写了equals方法, 否则,equals为真的两元素,其hashcode也一定相同
 
那么我遇到的问题也好解决了:
第一种情况,两个都是Int数组,arr1和arr2的hashcode就不相同,arr2找到的hashmap中的位置与arr1就不相同,不需要用equals方法,arr2就可以插入.
第二种情况,两个是arraylist,arr2的hashcode和arr1的hashcode相同,有兴趣的同学可以去看一下AbstactList.java
中HashCode()方法,到底是怎么计算arraylist的hashcode值,这里我贴出来
public int hashCode() {
        int hashCode = 1;
        for (E e : this)
            hashCode = 31*hashCode + (e==null ? 0 : e.hashCode());
        return hashCode;
    }

因为hashcode值相同,则找到了相同的位置,于是使用equals()方法,arraylist的equals方法如下:

 public boolean equals(Object o) {
        if (o == this)
            return true;
        if (!(o instanceof List))
            return false;

        ListIterator<E> e1 = listIterator();
        ListIterator<?> e2 = ((List<?>) o).listIterator();
        while (e1.hasNext() && e2.hasNext()) {
            E o1 = e1.next();
            Object o2 = e2.next();
            if (!(o1==null ? o2==null : o1.equals(o2)))
                return false;
        }
        return !(e1.hasNext() || e2.hasNext());
    }

对每一个元素调用其equals方法,都为true就返回为真,所以这一看一下Integer的equal()


public boolean equals(Object obj) {
        if (obj instanceof Integer) {
            return value == ((Integer)obj).intValue();
        }
        return false;
    }

Integer的equals方法,值相同则返回为真,所以arr2和arr1中依次循环比较,每个值得equals都返回为真,则arr2.equals(arr1)
返回真,所以就不能插入


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值