共同学习Java源码--常用数据类型--String(九)

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

这个方法非常重要,就是计算hashcode的方法。hashCode是jdk根据对象的地址或者字符串或者数字算出来的int类型的数值。首先定义一个int变量h,赋值为hash,默认赋值为0。然后判断如果h为0,而且value有了元素之后,定义val变量引用value,然后进入循环,循环次数为value的长度。每次循环都让31乘以h的值再加上val的每一个元素,val引用了value,然后循环结束,将最后所得的h赋值给hash,最后返回h。

    public int indexOf(int ch) {
        return indexOf(ch, 0);
    }

    public int indexOf(int ch, int fromIndex) {
        final int max = value.length;
        if (fromIndex < 0) {
            fromIndex = 0;
        } else if (fromIndex >= max) {
            // Note: fromIndex might be near -1>>>1.             return -1;
        }


        if (ch < Character.MIN_SUPPLEMENTARY_CODE_POINT) {
            // handle most cases here (ch is a BMP code point or a             // negative value (invalid code point))             final char[] value = this.value;
            for (int i = fromIndex; i < max; i++) {
                if (value[i] == ch) {
                    return i;
                }
            }
            return -1;
        } else {
            return indexOfSupplementary(ch, fromIndex);
        }
    }

    private int indexOfSupplementary(int ch, int fromIndex) {
        if (Character.isValidCodePoint(ch)) {
            final char[] value = this.value;
            final char hi = Character.highSurrogate(ch);
            final char lo = Character.lowSurrogate(ch);
            final int max = value.length - 1;
            for (int i = fromIndex; i < max; i++) {
                if (value[i] == hi && value[i + 1] == lo) {
                    return i;
                }
            }
        }
        return -1;
    }

这三个方法要一起看,第一个方法是返回某个字符在该字符串中的下标,调用的是第二个方法,并为第二个方法的第二个参数传0,也就是从本字符串的0下标开始搜索。最重要的是这三个方法的核心参数是int ch也就是要搜索的代码点。

第二个方法首先先将value数组的长度固化,并且赋值于一个final的临时变量,然后判断第二个参数也就是开始搜索的起始下标,如果小于0则返回0,如果大于value的长度,则返回-1。

接下来再进行判断,如果要判断的代码点小于那个常量,那个常量的值是65536,也就是2的16次方,java中char占两个字节,取值范围是0~65535。如果在65535之内,则遍历整个value数组,看哪个元素和参数相等,就返回相应下标,否则返回-1。

如果要搜索的代码点大于65535,则调用第三个方法。第三个方法先判断该代码点是否是有效的代码点,代码点之前几篇有介绍,具体的实现是先将该代码点右移十六位,所得的值与最大代码点加一后右移16位所得的结果进行比较,如果小于则为true,如果为false,第三个方法也返回-1,最大代码点是1114111,加一后右移16位是17,这个代码点1114111的意义暂时不清楚,为什么要右移16位也暂时不清楚。

判定属于有效代码点后,开始计算该参数代码点的highSurrogate和lowSurrogate,也就是高代理和低代理。这个高代理和低代理是什么我不知道,但是计算方法是,高代理是将参数代码点右移10位,加上D800这个代码点减去65536右移16位之后所得数的差,然后强转为char类型,低代理是将参数代码点与1023进行按位运算,就是将两个数转换成二进制,每一位进行比较,如果两个数的对应数位上有一个是0,那么结果对应数位就是0,最后得到的结果转换成十进制,然后再加上DC00这个代码点,得到的结果进行强转为char。

然后遍历value数组,判断value的每一位是否是该参数代码点的高代理且下一位是否是该参数的低代理,判断成功则返回该位的下标。

    原文作者:分享你刚编的故事
    原文地址: https://zhuanlan.zhihu.com/p/46620606
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞