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 &&