String类的hashCode()方法源码分析
编译期间,字符串的最大长度不能超越65535个字节,即编译期间的String字符串的最大长度为65534个字节,不然就会编译报错。运行期间,String的最大长度就要看Integer.MAX_VALUE的值了,即:2^31 - 1个字节。不管怎样,String的最大长度就不能超过虚拟机当前最大内存设置。
Object类中的hashCode()方法:
- 同一个对象,hashCode必须相同;如果两个对象的equals相等,那么hashCode也必须要相等!
- hashCode()方法是native本地方法,是C++代码,hashCode的值,不一定是指向对象的内存地址,具体是什么值,底层依赖于JVM的具体实现,但是,同一个对象的hashCode()必须要唯一,所以hashCode就是唯一标识一个对象的。
- 在每个覆盖了equals()方法的类中,也必须覆盖hashCode()方法,因为如果不这样做的话,就会违反Object.hashCode()的通用约定,从而导致该类无法结合所有基于散列的集合一起正常运作,这样的集合包括HashMap、HashSet和Hashtable
String类中的hashCode()方法:
- String字符串重写了equals()方法,就必须要同时重写hashCode()方法,目的是确保:equals相等,hashCode也必须要相等。
- String字符串的equals()和hashCode()方法都是基于字符串内容去计算的,由于字符串内容相同,所以equals()就相同,hashCode()也相同。
- String类的equals()方法就是将String字符串转为char[]数组,然后while循环遍历比较两个char[]数组的字符是否相等,如果相等返回true,如果有一个不相等,则直接返回false。
String类中的hashCode()方法源码:
public int hashCode() {
int h = hash;
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()计算公式为:s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1] => 乘法散列
使用字符串中当前每个字符的ASCII码值 * 31的(字符串长度 - 1 -2 -3)次幂进行累加
关于hashCode()计算过程中,为什么使用了数字31,主要有以下几个原因:
1. 使用质数计算哈希码,由于质数的特性,它与其它数字相乘之后,计算结果唯一的概率更大, 哈希冲突的概率更小。
2. 使用的质数越大,哈希冲突的概率越小,但是计算的速度也越慢,31是哈希冲突和性能的折中
3. JVM会自动对31进行优化:31 * i == (i << 5) - i
package com.gch.demo;
/**
* String类重写了hashCode()和equals()方法
* 由于String类的hashCode()方法和equals()方法是基于变量的字符串的内容去计算
* 因此只要String类的对象的内容相同,则hashCode()和equals()一定相同
*/
public class StringDemo {
public static void main(String[] args) {
String s1 = "hello";
String s2 = "hello";
String s3 = new String("hello");
int hashCode1 = s1.hashCode();
int hashCode2 = s2.hashCode();
int hashCode3 = s3.hashCode();
System.out.println(hashCode1); // 99162322
System.out.println(hashCode2); // 99162322
System.out.println(hashCode3); // 99162322
}
}
JDK 8及其之前String底层由char[]数组构成的(就是对字符数组的封装),JDK 9之后,String底层采用的byte[]数组。
String有没有长度限制?
- 有长度限制。
编译期间
根据虚拟机规范:
编译期间,字符串的最大长度不能超越65535个字节,即编译期间的String字符串的最大长度为65534个字节,不然就会编译报错。
运行期间
运行期间,String的最大长度就要看Integer.MAX_VALUE的值了,即:2^31 - 1个字节。
不管怎样,String的最大长度就不能超过虚拟机当前最大内存设置。
数组有没有length()方法?String呢?
- 数组没有length()方法,但是有length属性,String有length()方法。
package com.gch.demo;
/**
* @author GAO
* @date 2023-12-15
*/
public class LengthDemo {
public static void main(String[] args) {
String str = "Java";
String[] languages = {"Java","Python","PHP"};
System.out.println(str.length()); // 字符串有length()方法
System.out.println(languages.length); // 数组有length属性
}
}
注意:从JDK 7开始,switch是可以用在字符串String上的。
String类是可变的吗?为什么?
Java中的String类设计是不可变的,String类是final类型的,不能被继承,其对应的char字符类型的value[]数组被定义成private final的,说明不能通过外界修改,即不可变~!
更多推荐
所有评论(0)