HashSet的实现原理去重

集合 的体系:
------------| Collection 单例集合的根接口
----------------| List  如果是实现了List接口的集合类,具备的特点: 有序,可重复。 
-------------------| ArrayList  ArrayList 底层是维护了一个Object数组实现的。 特点: 查询速度快,增删慢。
-------------------| LinkedList LinkedList 底层是使用了链表数据结构实现的, 特点: 查询速度慢,增删快。
-------------------| Vector(了解即可)  底层也是维护了一个Object的数组实现的,实现与ArrayList是一样的,但是Vector是线程安全的,操作效率低。

----------------| Set  如果是实现了Set接口的集合类,具备的特点: 无序,不可重复。
-------------------| HashSet  底层是使用了哈希表来支持的,特点: 存取速度快. 

hashSet的实现原理:
    往Haset添加元素的时候,HashSet会先调用元素的hashCode方法得到元素的哈希值 ,
    然后通过元素 的哈希值经过移位等运算,就可以算出该元素在哈希表中 的存储位置。
    
    情况1: 如果算出元素存储的位置目前没有任何元素存储,那么该元素可以直接存储到该位置上。

    情况2: 如果算出该元素的存储位置目前已经存在有其他的元素了,那么会调用该元素的equals方法与该位置的元素再比较一次,如果equals返回的是true,那么该元素与这个位置上的元素就视为重复元素,不允许添加,如果equals方法返回的是false,那么该元素运行 添加。

问题1:Java中Set的contains()方法 —— hashCode与equals方法的约定及重写原则

 

Set的contains(Object o) 方法详解

Java的API文档指出: 当且仅当 本set包含一个元素 e,并且满足(o==null ? e==null : o.equals(e))条件时,contains()方法才返回true. 因此 contains()方法 必定使用equals方法来检查是否相等.

equals()与hashCode()方法之间的设计实现原则为:

如果两个对象相等(使用equals()方法),那么必须拥有相同的哈希码(使用hashCode()方法).

即使两个对象有相同的哈希值(hash code),他们不一定相等.意思就是: 多个不同的对象,可以返回同一个hash值.

hashCode()的默认实现是为不同的对象返回不同的整数.有一个设计原则是,hashCode对于同一个对象,不管内部怎么改变,应该都返回相同的整数值.

问题2:JAVA HashSet 去除重复值原理]

Java中的set是一个不包含重复元素的集合,确切地说,是不包含e1.equals(e2)的元素对。Set中允许添加null。Set不能保证集合里元素的顺序。

在往set中添加元素时,如果指定元素不存在,则添加成功。也就是说,如果set中不存在(e==null ? e1==null : e.queals(e1))的元素e1,则e1能添加到set中。

Hashcode约定

1. 在一个应用程序执行期间,如果一个对象的equals方法做比较所用到的信息没有被修改的话,则对该对象调用hashCode方法多次,它必须始终如一地返回同一个整数。

2. 如果两个对象根据equals(Object o)方法是相等的,则调用这两个对象中任一对象的hashCode方法必须产生相同的整数结果。

3. 如果两个对象根据equals(Object o)方法是不相等的,则调用这两个对象中任一个对象的hashCode方法,不要求产生不同的整数结果。但如果能不同,则可能提高散列表的性能。

package com.darren.test.overide;
 
public class CustomString {
    private String value;
 
    public CustomString() {
        this("");
    }
 
    public CustomString(String value) {
        this.value = value;
    }
 
    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
 
            return true;
        } else if (obj instanceof CustomString) {
            CustomString customString = (CustomString) obj;
 
            return customString.value.equals(value);
        } else {
 
            return false;
        }
    }
 
    @Override
    public int hashCode() {
        // return super.hashCode();
        return 1;
    }
}
package com.darren.test.overide;
 
import java.util.HashSet;
import java.util.Set;
 
public class HashSetTest {
    public static void main(String[] args) {
        String a = new String("A");
        String b = new String("A");
        
        CustomString c = new CustomString("B");
        CustomString d = new CustomString("B");
        
        System.out.println("a.equals(b) == " + a.equals(b));
        System.out.println("c.equals(d) == " + c.equals(d));
        
        Set<Object> set = new HashSet<Object>();
        set.add(a);
        set.add(b);
        set.add(c);
        set.add(d);
        
        System.out.println("set.size() == " + set.size());
        
        for (Object object : set) {
            System.out.println(object);
        }
    }
}
//输出结果
a.equals(b) == true
c.equals(d) == true
set.size() == 2
com.darren.test.overide.CustomString@1
A

在HashSet中,基本的操作都是有HashMap底层实现的,因为HashSet底层是用HashMap存储数据的。当向HashSet中添加元素的时候,首先计算元素的hashcode值,然后用这个(元素的hashcode)%(HashMap集合的大小)+1计算出这个元素的存储位置,如果这个位置位空,就将元素添加进去;如果不为空,则用equals方法比较元素是否相等,相等就不添加,否则找一个空位添加。https://blog.csdn.net/zpf336/article/details/42397415

总结一下:hashmap 判断是否包含此key需要重写hashcode和equals /ArrayList 只需要重写equals即可

如何重写 看这里

https://www.cnblogs.com/yuxiaole/p/9570850.html

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值