key值为null时访问
我们知道插入元素的key值是允许为null的。 我们看一下这部分的源码:java
private V putForNullKey(V value) { for (Entrye = table[0]; e != null; e = e.next) { if (e.key == null) { V oldValue = e.value; e.value = value; e.recordAccess(this); return oldValue; } } modCount++; addEntry(0, null, value, 0); return null; }
可以看到,当key=null时,对应的数据存储在链表中内部数组的第一个位置。 知道了它是怎么保存的,那么获取就简单了:在内部数组的第一个位置编译列表,找到key=null的数据项,返回数据项中的值。
private V getForNullKey() { for (Entrye = table[0]; e != null; e = e.next) { if (e.key == null) return e.value; } return null; }
和方法
在之前的博文:《基础知识-》原理分析中,我们可以知道key必须实现它的sum方法,两者缺一不可。但是大家知道,这两个方法默认都是从对象继承的。 我们看一下原生的实现:数组
public native int hashCode(); public boolean equals(Object obj) { return (this == obj); }
可以看到,该方法使用关键字表明其实现是调用C/C++的底层函数来实现,并且该方法认为只有当两个对象的引用指向同一个对象时,才认为是equal.
如果你自定义一个类,并且不重写方法和方法,并且使用这个类的对象作为键值来保存,那么在读取的时候,除非你使用了和保存时一模一样的引用,否则该对象用作key值,否则永远得不到key对应的value。 IDE
下面是一个很好的 sum 实现的例子:
public final class PhoneNumber { private final short areaCode; private final short prefix; private final short lineNumber; public PhoneNumber(int areaCode, int prefix, int lineNumber) { this.areaCode = (short) areaCode; this.prefix = (short) prefix; this.lineNumber = (short) lineNumber; } @Override public boolean equals(Object o) { if (o == null) return false; if (o == this) return true; if (!(o instanceof PhoneNumber)) return false; PhoneNumber pn = (PhoneNumber)o; return pn.lineNumber == lineNumber && pn.prefix == prefix && pn.areaCode == areaCode; } @Override public int hashCode() { int result = 17; result = 31 * result + areaCode; result = 31 * result + prefix; result = 31 * result + lineNumber; return result; } }
实施建议如下:
表现
1. 将一个非零常量值,例如17,保存在一个名为int类型的变量中。
2、对于对象中的每个关键域f(指方法中涉及到的每个域),完成以下步骤:
A。 计算该字段的int类型的哈希码c:
我。 如果该字段是类型,则计算 (f?1:0)。
二. 如果字段的类型为 byte、char、short 或 int,则计算 (int)f。
三. 如果字段是long类型,则计算(int)(f^(f>>>32))。
四. 如果字段为float类型,则计算Float.(f)。
v. 如果该字段是类型,则计算.(f),然后按照步骤2.a.iii计算得到的long类型值的哈希值。
六. 如果该字段是一个对象引用,并且递归调用该类的方法来比较该字段,那么也会针对该字段递归调用该方法。 如果需要更复杂的比较,请计算该字段的范式 ( ),然后针对该范式调用它。 如果该字段的值为空,则返回0(也可以接受其他常量)。
七. 如果字段是数组,则每个元素必须被视为单独的字段。 即递归地应用上述规则,为每个重要元素计算一个哈希码,然后根据步骤2.b中的方法组合这些哈希值。 如果数组字段中的每个元素都很重要,您可以使用版本 1.5 中添加的方法之一。
b. 根据以下公式,将步骤2.a计算出的哈希码c合并为: = 31 * + c; //这里31是一个奇素数,而且它有一个非常好的特性,就是用移位位和减法代替乘法可以达到更好的性能:31*i == (i