您的位置:首页 > 汽车 > 新车 > 网站工程前端_怎样优化手机网站_聊城seo培训_排名优化工具

网站工程前端_怎样优化手机网站_聊城seo培训_排名优化工具

2024/12/28 15:59:27 来源:https://blog.csdn.net/qq_62694876/article/details/143912142  浏览:    关键词:网站工程前端_怎样优化手机网站_聊城seo培训_排名优化工具
网站工程前端_怎样优化手机网站_聊城seo培训_排名优化工具

剖析equals方法

1、对于Object来说,其equals()方法底层实现就是"==",都是比较对象的引用是否相等,下为JDK源码。

Object c = 1;
Object d = 1;
boolean equals = c.equals(d);public boolean equals(Object obj) {return (this == obj);
}

2、在JDK中其他类中通常会重写equals()方法,例如:Integer、String,源码如下。

Integer会先将Integer对象转换成基础类型int值来比较,所以此时就不再是比较两个对象引用,是比较两个对象的值是否相等。

Integer a = 1;
Integer b = 1;
boolean equals = a.equals(b);public boolean equals(Object obj) {if (obj instanceof Integer) {return value == ((Integer)obj).intValue();}return false;
}@Override
public int hashCode() {return Integer.hashCode(value); // 由于 Integer 是不可变类,其 hashCode 就是整数值本身。
}

 String和Integer一样,引用比较重写成了值比较了。

String a = "a";
String b = "a";
boolean equals = a.equals(b);public boolean equals(Object anObject) {if (this == anObject) {return true; // 引用相同返回 true,引用相同,那么值肯定相同了}return (anObject instanceof String aString)&& (!COMPACT_STRINGS || this.coder == aString.coder)&& StringLatin1.equals(value, aString.value); // equals 为下面的 equals 方法
}@IntrinsicCandidate
public static boolean equals(byte[] value, byte[] other) {if (value.length == other.length) {for (int i = 0; i < value.length; i++) { // 循环每个字符对比,本质是值比较if (value[i] != other[i]) {return false;}}return true;}return false;
}// JDK17
public int hashCode() {int h = hash;  // 缓存的 hash 值if (h == 0 && !hashIsZero) {h = isLatin1() ? StringLatin1.hashCode(value): StringUTF16.hashCode(value);if (h == 0) {hashIsZero = true; // 标记 hashCode 为 0 的情况} else {hash = h; // 缓存 hashCode}}return h;
}static int hashCode(byte[] value) {int h = 0;for (int i = 0; i < value.length; i++) {h = 31 * h + (value[i] & 0xff);}return h;
}static int hashCode(byte[] value) {int h = 0;for (int i = 0; i < value.length; i += 2) {h = 31 * h + getChar(value, i);}return h;
}static char getChar(byte[] val, int index) {return (char) (((val[index] & 0xff) << 8) | (val[index + 1] & 0xff));
}

 JDK17对String的hashcode()方法与早期版本相比进行了优化,主要是为了更好地适应 String 的内部存储机制的变化以及性能提升。从 JDK9开始,String 使用了一种称为 Compact Strings 的机制。即:String 内部不再总是使用 char[] 存储,而是根据字符内容选择 byte[] 存储。如果所有字符是 Latin-1(单字节字符,0~255),则使用 byte[],以节省内存。如果有非 Latin-1 字符(需要双字节存储),则仍使用 UTF-16 编码。

1、hash:用于缓存计算过的 hashCode,避免重复计算。

2、hashIsZero:标志变量,处理特殊情况:

  • 如果字符串的 hashCode 计算结果为 0,会将 hashIsZero 标记为 true,防止后续重复计算。
  • 区分未计算和计算后结果为 0 的情况。
  • isLatin1():判断字符串是否为 Latin-1 编码。
    • 如果是 Latin-1,则调用 StringLatin1.hashCode(value)
      • Latin-1 的 hashCodeStringLatin1.hashCode): 遍历 byte[] 数组,使用与原始实现相同的算法(31 为乘数)。
    • 否则调用 StringUTF16.hashCode(value)
      • UTF-16 的 hashCodeStringUTF16.hashCode): 遍历 byte[] 数组(每两个字节表示一个 char),计算哈希值。

JDK17的优点

支持 Compact Strings

  • 根据字符编码选择不同的计算方式,提高内存效率和性能。

性能优化

  • 使用 hashIsZero 减少重复计算。
  • 针对 Latin-1 和 UTF-16 分开处理,减少不必要的判断和操作。

兼容性

  • 虽然内部实现发生了变化,但对外部来说行为与早期版本保持一致。

同时上述说了重写equals()方法,还需要重写hashCode 方法。

根据 Object 类的规范:

如果两个对象根据 equals 方法比较是相等的,那么它们的 hashCode 值也必须相等。

原因:

如果只重写了 equals 而没有重写 hashCode,会导致在使用哈希表(如 HashMapHashSet)时出现问题,因为这些集合依赖于对象的 hashCode 值来确定存储位置。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com