• Java基础--HashCode


    如果一个类的对象要用做hashMap的key,那么一定要注意覆盖该类的equals和hashCode方法。

    equals()是基类Object的方法,用于判断对象是否有相同地址及是否为同一对象

    public boolean equals(Object obj) {
            return (this == obj);
        }

    hashCode()是基类Object的native方法,返回int。 

    hashCode的通用约定: 

    1.在程序运行期间,只要对象不改变,hashCode方法返回的值始终如一。

    2.若两个对象equals方法返回相同,hashCode也应该相同。

    3.若两个对象equals方法返回不同,hashCode也应该不同。

    根据上面的约定,覆盖hashCode方法时注意:

    1.需使用对象属性中关键且独立的部分

    2.不要使用equals方法中未使用的属性

    3.使用equals方法中使用的属性

    String类的hashCode方法:

     1 public int hashCode() {
     2         int h = hash;
     3         if (h == 0 && value.length > 0) {
     4             char val[] = value;
     6             for (int i = 0; i < value.length; i++) {
     7                 h = 31 * h + val[i];
     8             }
     9             hash = h;
    10         }
    11         return h;
    12     }

    32*d == d<<5   aka   31*d == d<<5-d    

    一个例子:

    ----------------------------

     1 class TestClass {
     2     // 若类较复杂,建议将hashCode缓存,以提高性能
     3     private volatile int hashCode = 0;
     4 
     5     private int i;
     6     private boolean b;
     7     private char c; // 或byte short
     8     private long l;
     9     private float f;
    10     private double d;
    11     private int[] aa;
    12     private String s;
    13 
    14     @Override
    15     public boolean equals(Object o) {
    16         if (o == this) {
    17             return true;
    18         }
    19         if (!(o.getClass() == getClass())) {
    20             return false;
    21         }
    22         TestClass ot = (TestClass) o;
    23         return i == ot.i && b == ot.b && c == ot.c && l == ot.l && Float.compare(f, ot.f) == 0 && Double.compare(d, ot.d) == 0
    24                 && Arrays.equals(aa, ot.aa) && s.equals(ot.s);
    25     }
    26 
    27     @Override
    28     public int hashCode() {
    29         int result = hashCode;
    30         if (result == 0) {
    31             result = 31 * result + i;
    32             result = 31 * result + Boolean.hashCode(b);
    33             result = 31 * result + (int)c;
    34             result = 31 * result + Long.hashCode(l);
    35             result = 31 * result + Float.hashCode(f);
    36             result = 31 * result + Double.hashCode(d);
    37             result = 31 * result + Arrays.hashCode(aa);
    38             result = 31 * result + s.hashCode();
    39             hashCode = result;
    40         }
    41         return result;
    42     }
    43     
    44     @Override
    45     public String toString(){
    46         //
    47         return s;
    48     }
    49 
    50 }

    ----------------------------

    HashMap

    HashMap默认初始容量16,加载因子0.75,容量也就是内部数组table的大小,总是2的n次方,table中的元素为链表,链表的元素为包含key,value,hash和下一元素的Entry。

    put方法根据key的hashCode来计算元素在table中的存放位置,不同的key将均匀的散列在table中。

    HashMap的扩容将重新计算所有元素在新数组中的位置,所以如果预计存放大量数据,初始容量应该设置更大。

  • 相关阅读:
    【转】WCF入门教程六[一个简单的Demo]
    【转】WCF入门教程五[WCF的通信模式]
    【转】WCF入门教程四[WCF的配置文件]
    【转】WCF入门教程三[WCF的宿主]
    【转】WCF入门教程二[WCF应用的通信过程]
    【转】WCF入门教程一[什么是WCF]
    【转】浅谈.net remoting 与webservice
    【转】Microsoft .Net Remoting之Remoting事件处理全接触
    egret升级经验记录
    cmder小技巧
  • 原文地址:https://www.cnblogs.com/luangeng/p/6029482.html
Copyright © 2020-2023  润新知