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)次幂进行累加
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[]数组。
根据虚拟机规范:
编译期间,字符串的最大长度不能超越65535个字节,即编译期间的String字符串的最大长度为65534个字节,不然就会编译报错。
运行期间,String的最大长度就要看Integer.MAX_VALUE的值了,即:2^31 - 1个字节。
不管怎样,String的最大长度就不能超过虚拟机当前最大内存设置。?
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的,说明不能通过外界修改,即不可变~!