String源码

String其实就是一个char集合

String只是大致看了下,基本都是对char数组的操作,包括判断是否为空,或者取指定下标数据等等。。

String类是final修饰的,所以不可被继承,实现了java.io.Serializable, Comparable, CharSequence等接口,说明String是可以序列化和反序列化的,并且支持自定义的字符串比较。

主要记录下equals和hashCode两个方法,这两个方法都是重写的Object类的。

Object类的equals方法其实使用的还是"=="

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

而hashCode不是用java写的,就不多说了

下面是String重写的

public boolean equals(Object anObject) {
        if (this == anObject) {
            return true;
        }
        if (anObject instanceof String) {
            String anotherString = (String)anObject;
            int n = value.length;
            if (n == anotherString.value.length) {
                char v1[] = value;
                char v2[] = anotherString.value;
                int i = 0;
                while (n-- != 0) {
                    if (v1[i] != v2[i])
                        return false;
                    i++;
                }
                return true;
            }
        }
        return false;
    }

首先判断对象地址是否相同,地址相同就直接返回true,地址不相同再判断字符串长度是否相同,最后再对字符串的每个字符一一进行对比。

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;
    }

可以举个例子:

当前字符集是ASCII

System.out.println("a".hashCode());//97  对应的是ASCII码表a的十进制数

System.out.println("b".hashCode());//98  对应的是ASCII码表a的十进制数

System.out.println("ab".hashCode());//3105  根据h=31*h+val[i]来算 第一遍循环hash=0,也就是h=0,第一遍循环走完h='a',  第二遍循环其实就是'a'*31+'b'=3105

哈希的地址算法主要就是h = 31 * h + val[i],每次是将上次一算出的hash值乘以31 然后再加上当前字符编码值,由于这里使用的是int肯定会有一个上限,当字符串超过上限,HashCode的正确性就无法保证了,所以这点可以推断出HashCode存在不相同字符拥有相同HashCode。

字符串相同,哈希一定相同,哈希相同,字符串不一定相同。

补充:

String的hashcode计算为什么选择31这个质数来计算,主要是是因为31 * i = (i << 5) - i,这样JVM使用位运算速度更快,而且冲突率也会比较小。

参考https://www.cnblogs.com/nullllun/p/8350178.html

你可能感兴趣的:(jdk1.8源码)