zoukankan      html  css  js  c++  java
  • java源码解析之String类(三)

      上一节我们主要讲了String类的一些不是很常用的方法,其中需要掌握的如下,我就不再赘述了

    public int length()
    public boolean isEmpty() 
    public byte[] getBytes()
    public byte[] getBytes(String charsetName)
    public char charAt(int index)
    public boolean equals(Object anObject)
    public boolean equalsIgnoreCase(String anotherString)

      继续今天的内容

        /*
         * String实现接口Comparable中的compareTo方法,通过源码我们可以看出s1.compareTo(s2)依次拿出s1和s2的第k个字符进行比较
         * 如果某两个不相等,则返回这两个字符的差:c1-c2(ps:这里你需要知道java中byte、short、char在参与运算的时候将自动转换为int类型,所以最后返回的是int类型)
         * 最后我们得出结论:
         *         返回值是0,则两个字符串相等
         */
        public int compareTo(String anotherString) {
            int len1 = value.length;
            int len2 = anotherString.value.length;
            int lim = Math.min(len1, len2);
            char v1[] = value;
            char v2[] = anotherString.value;
    
            int k = 0;
            while (k < lim) {
                char c1 = v1[k];
                char c2 = v2[k];
                if (c1 != c2) {
                    return c1 - c2;
                }
                k++;
            }
            return len1 - len2;
        }
    
        /*
         * Comparator是一个比较器,String采用成员内部类的形式定义了一个比较器,comparator和comparable一时半会也讲不清楚
         * 这里你只需要知道二者都是用于比较的,comparable比较的是自然排序(其实所谓的自然排序也是程序猿规定好的),比较简单,大部分是内置的,比如说String和Integer等类都有
         * 而comparator是比较一些 比较复杂的,用户自己定义的,比如说下面的不区分大小写的比较就是用comparator实现的。仔细看源代码很简单的。
         */
        public static final Comparator<String> CASE_INSENSITIVE_ORDER = new CaseInsensitiveComparator();
    
        private static class CaseInsensitiveComparator implements Comparator<String>, java.io.Serializable {
            // use serialVersionUID from JDK 1.2.2 for interoperability
            private static final long serialVersionUID = 8575799808933029326L;
    
            public int compare(String s1, String s2) {
                int n1 = s1.length();
                int n2 = s2.length();
                int min = Math.min(n1, n2);
                for (int i = 0; i < min; i++) {
                    char c1 = s1.charAt(i);
                    char c2 = s2.charAt(i);
                    if (c1 != c2) {
                        c1 = Character.toUpperCase(c1);
                        c2 = Character.toUpperCase(c2);
                        if (c1 != c2) {
                            c1 = Character.toLowerCase(c1);
                            c2 = Character.toLowerCase(c2);
                            if (c1 != c2) {
                                // No overflow because of numeric promotion
                                return c1 - c2;
                            }
                        }
                    }
                }
                return n1 - n2;
            }
    
            //替换反序列化的对象
            private Object readResolve() {
                return CASE_INSENSITIVE_ORDER;
            }
        }
    
        /*
         * String的另一个比较,也就是不区分大小写的比较,内部封装着comparator的实现类的对象
         * 
         * 总结:String有两种比较方式
         *         1.compareTo         按照自然顺序比较,区分大小写
         *         2.compareToIgnoreCase   不区分大小写的比较
         * 虽然二者方法名很像,但是实现原理完全不一样!!!!
         */
        public int compareToIgnoreCase(String str) {
            return CASE_INSENSITIVE_ORDER.compare(this, str);
        }
    
        /*
         * 测试两个字符串区域是否相等,还记得吗?equalsIgnoreCase方法的内部其实使用的就是regionMatches
         */
        public boolean regionMatches(int toffset, String other, int ooffset, int len) {
            char ta[] = value;
            int to = toffset;
            char pa[] = other.value;
            int po = ooffset;
            // Note: toffset, ooffset, or len might be near -1>>>1.
            if ((ooffset < 0) || (toffset < 0) || (toffset > (long) value.length - len)
                    || (ooffset > (long) other.value.length - len)) {
                return false;
            }
            while (len-- > 0) {
                if (ta[to++] != pa[po++]) {
                    return false;
                }
            }
            return true;
        }
    
        /*
         * 
         */
        public boolean regionMatches(boolean ignoreCase, int toffset, String other, int ooffset, int len) {
            char ta[] = value;
            int to = toffset;
            char pa[] = other.value;
            int po = ooffset;
            // Note: toffset, ooffset, or len might be near -1>>>1.
            if ((ooffset < 0) || (toffset < 0) || (toffset > (long) value.length - len)
                    || (ooffset > (long) other.value.length - len)) {
                return false;
            }
            while (len-- > 0) {
                char c1 = ta[to++];
                char c2 = pa[po++];
                if (c1 == c2) {
                    continue;
                }
                if (ignoreCase) {
    
                    char u1 = Character.toUpperCase(c1);
                    char u2 = Character.toUpperCase(c2);
                    if (u1 == u2) {
                        continue;
                    }
    
                    if (Character.toLowerCase(u1) == Character.toLowerCase(u2)) {
                        continue;
                    }
                }
                return false;
            }
            return true;
        }
    
        /*
         * 从字符串开始位置toffset去匹配目标字符串prefix,很常用的方法,代码原理很简单
         *         startsWith(String prefix, int toffset)
         *         startsWith(String prefix)
         *         endsWith(String prefix)
         */
        public boolean startsWith(String prefix, int toffset) {
            char ta[] = value;
            int to = toffset;
            char pa[] = prefix.value;
            int po = 0;
            int pc = prefix.value.length;
            // Note: toffset might be near -1>>>1.
            if ((toffset < 0) || (toffset > value.length - pc)) {
                return false;
            }
            while (--pc >= 0) {
                if (ta[to++] != pa[po++]) {
                    return false;
                }
            }
            return true;
        }
    
        public boolean startsWith(String prefix) {
            return startsWith(prefix, 0);
        }
    
        public boolean endsWith(String suffix) {
            return startsWith(suffix, value.length - suffix.value.length);
        }
    
        /*
         * String重写了equals,也重写了hashCode,这里我解释一下Object中的hashCode返回的是什么,因为是原生方法,所以源代码当中并没有
         * 但是自己去试试就知道是什么了,创建一个类(不重写hashCode)并实例化,输出的是一个int类型的,然后重写再输出得到的还是相同长度的int类型,
         *     
         */
        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;
        }
        
        
  • 相关阅读:
    控制反转和依赖注入
    共识机制是什么?
    实用拜占庭容错算法PBFT
    三种框架对比react vue 和Angular对比
    go语言学习笔记
    激活方法总结
    钱包助记词
    简历中存在的问题的处理
    why we use Symbols in Hash
    compact过滤数组中的nil
  • 原文地址:https://www.cnblogs.com/gollong/p/9360947.html
Copyright © 2011-2022 走看看