美文网首页
Guava学习笔记(2)Strings

Guava学习笔记(2)Strings

作者: 懵逼猴 | 来源:发表于2018-05-20 12:58 被阅读0次

    从Guava.Strings的提供的一些方法开始学习

    padStart和padEnd方法

    • 先来看一下方法声明
    padStart(String string, int minLength, char padChar)
    padEnd(String string, int minLength, char padChar)
    

    padStart 返回一个字符串,其长度至少为minLength,如果长度小于minLength,则在字符串的前面添加若干个padChar,直到长度为minLength;如果长度大于minLength则直接返回字符串。padEnd则是长度不够的时候在字符串末尾添加padChar。

    repeat方法

    • 将一个字符串重复几次之后再输出。下面看一下代码的实现
    public static String repeat(String string, int count) {
        // 首先判断输入的参数是否合法
        checkNotNull(string); 
        if (count <= 1) {
          checkArgument(count >= 0, "invalid count: %s", count);
          return (count == 0) ? "" : string;
        }
    
        // IF YOU MODIFY THE CODE HERE, you must update StringsRepeatBenchmark
        final int len = string.length();
        final long longSize = (long) len * (long) count;
        final int size = (int) longSize;
       // 如果字符长度超出int范围则抛出错误
        if (size != longSize) {
          throw new ArrayIndexOutOfBoundsException("Required array size too large: " + longSize);
        }
    
        final char[] array = new char[size];
        // 将字符串中的字符复制到目标字符数组中,实际也调用了System.arraycopy这个本地方法
        string.getChars(0, len, array, 0);
        int n;
       // 这里使用到了移位运算,使得每次复制的数据都是上一次的2倍,总的循环的次数变为log(count)次,提高了效率
        for (n = len; n < size - n; n <<= 1) {
          System.arraycopy(array, 0, array, n, n);
        }
        // 如果count为奇数,则还要进行依次额外的复制操作
        System.arraycopy(array, 0, array, n, size - n);
        return new String(array);
      }
    

    下面来看一下System.arraycopy这个方法的功能。首先看一下方法的声明

    arraycopy(Object src,  int  srcPos,Object dest, int destPos, int length)
    

    其功能是将源数组中从指定位置开始的数据复制到目标数组的指定位置之后的数据中去,复制数据的长度为length。也就是将源数组中指定位置srcPos到srcPos + length-1中的数据复制到 destPos到 destPos + length-1地方去。

    • commonPrefix(CharSequence a, CharSequence b)方法:返回两个字符串的最长公共前缀,如果没有则返回空字符串;commonSuffix返回两个字符串的最长公共后缀,实现与commonPrefix类似。commonPrefix部分源码如下:
        // 惯例,先判断参数的合法性
        checkNotNull(a);
        checkNotNull(b);
        int maxPrefixLength = Math.min(a.length(), b.length());
        int p = 0;
        while (p < maxPrefixLength && a.charAt(p) == b.charAt(p)) {
          p++;
        }
        if (validSurrogatePairAt(a, p - 1) || validSurrogatePairAt(b, p - 1)) {
          p--;
        }
        return a.subSequence(0, p).toString();
    

    说明:众所周知java采用UTF-16编码unicode字符集。UTF-16使用使用一个16位单元(两字节)或者两个16为单元表示一个unicode字符。使用两个单元的,前面那个单元叫highsurrogate 后面那个叫lowsurrogate。而char只占一个16位单元(两字节),在判断的时候使用的char来进行的比较。所以最后一个字符是占4字节的字符的时候会出现highsurrogate 相同,lowsurrogate不同,非同一个单元对,这就表明不是一个相同的字符。所以公共前缀的长度需要减一。

    • validSurrogatePairAt方法,判断两个连续的字符是否是一个utf-16的单元对的代码如下:
    static boolean validSurrogatePairAt(CharSequence string, int index) {
        return index >= 0
            && index <= (string.length() - 2)
            && Character.isHighSurrogate(string.charAt(index))
            && Character.isLowSurrogate(string.charAt(index + 1));
      }
    
    • 补充String 和 CharSequence 关系
      1.String 继承于CharSequence,也就是说String也是CharSequence类型。一般的使用情况都是使用String。
      2.CharSequence是一个接口,它只包括length(), charAt(int index), subSequence(int start, int end)这几个API接口。
      3.除了String实现了CharSequence之外,StringBuffer和StringBuilder也实现了CharSequence接口。
      需要说明的是,CharSequence就是字符序列,String, StringBuilder和StringBuffer本质上都是通过字符数组实现的!

    参考链接如下:

    Java中char占用几个字节
    StringBuffer.reverse()中surrogate pair的问题
    String和CharSequence的区别

    相关文章

      网友评论

          本文标题:Guava学习笔记(2)Strings

          本文链接:https://www.haomeiwen.com/subject/ywqudftx.html