Java 详述 HashSet 的 add 方法

本文深入探讨了Java中HashSet的add方法,揭示了其内部如何利用HashMap存储数据。通过源码分析,阐述了add方法调用HashMap的put方法,以及hashCode和putVal等关键步骤。当添加重复元素时,由于HashMap不允许key值重复,因此HashSet不会存储重复数据。同时,文章还讨论了自定义类泛型时,重写hashCode和equals方法对HashSet行为的影响。
摘要由CSDN通过智能技术生成

HashSet 的 add 方法

HashSet 的实质是利用 HashMap 的 key 值存储数据的容器,其有很多方法供我们使用,今天我们就详细说一下其中一个很重要的方法 add;即添加数据的方法;话不多少,先上例子和源码:

import java.util.HashSet;

public class Test {
	public static void main(String[] args) {
		HashSet<String> set = new HashSet<String>();
		set.add("Tom");	
	}
}

//add方法的源码
public boolean add(E e) {
        return map.put(e, PRESENT)==null;  //很明显,PRESENT 是个常量
    }


//put方法的源码
 public V put(K key, V value) {
        return putVal(hash(key), key, value, false, true);
    }

//hash方法的源码
static final int hash(Object key) {
        int h;
        return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
    }

//hashCode方法的源码 略过,一会详说

想要了解 HashSet 的 add  方法的执行过程,那就需要对源码进行了解,通过上例和源码我们可以看到:当我们创建好 HashSet 的对象 set 后,调用 add 方法进行赋值;add 方法会调用 map.put 方法;从这里我们可以看出来 HashSet 是利用 HashMap 的 key 值来存储数据的容器;方法会自定义一个常量,将每个 HashMap add 方法送过来的每一个值作为 key (例题中就是“Tom”),并将自定义的常量 PRESENT 的值作为 value 存入 HashMap 中作为一个 (k , v);例题中此时的这个(k , v)为 (“Tom”,PRESENT);

我们再看 put 的方法,这个很简单,就是直接调用 putVal 方法,并返回方法值;而 putVal 方法中会调一个 hash 方法; hash 方法就是一个简单的三目运算,也没什么,不过,重点来了,hash 方法中的三目运算中会包含一个 hashCode 方法;之所以源代码略过了,是因为这个方法涉及的内容比较多,我想分开来写,更容易看;

hashCode 方法不像 add 方法中其他几部分源码是固定的,而是根据泛型的不同而调用不同类型的 hashCode方法,接下来我们看两个典型的(常用的)hashCode 方法:

// String 中的 hashCode 方法
public int hashCode() {
        int h = hash;  //hash 是String的私有变量,初始值为0 
        if (h == 0 && value.length > 0) {
            char val[] = value;

            for (int i = 0; i < value.length; i++) {
                h = 31 * h + val[i];
            }
            hash = h;
        }
        return h;
    }

先看 String 中的 hashCode 方法:该方法会将参数转化成 char [ ];我们知道字符和 AXCII 存在一一对应关系;方法中的 for 循环就是利用 char [ ] 与 ASCII 的关系,将我们输入的字符串转换成对应的 int 的值返回;

//Integer 中的hashCode方法
public int hashCode() {
        return Integer.hashCode(value);
    }

public static int hashCode(int value) {
        return value;
    }

Integer 中的 hashCode 方法比 String 中的 hashCode 简单的多;其实就是直接返回参数值;

其他的基本数据类型封装类也是直接或间接的将参数处理并返回一个数值,在这就不一一举例了。

明白了 hashCode 方法,我们自然知道了 hash 方法会返回一个与参数相对应的一个值,然后来看我么的重头戏,putVal 方法;

//putVal 方法的源码
final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
                   boolean evict) {
        Node<K,V>[] tab; Node<K,V> p; int n, i;
        if ((tab = table) == null || (n = tab.length) == 0)
            n = (tab = resize()).length;
        if ((p = tab[i = (n - 1) & hash]) == null)
            tab[i] = newNode(hash, key, value, null);
        else {
            Node<K,V> e; K k;
            if (p.hash == hash &&
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值