[Guava源码日报](2)Strings分析

标签: guava
1264人阅读 评论(1) 收藏 举报
分类:

我们先看大体看一下Strings的源码:

  1. //
  2. // Source code recreated from a .class file by IntelliJ IDEA
  3. // (powered by Fernflower decompiler)
  4. //
  5. package com.google.common.base;
  6. import com.google.common.annotations.GwtCompatible;
  7. import com.google.common.annotations.VisibleForTesting;
  8. import com.google.common.base.Preconditions;
  9. import javax.annotation.CheckReturnValue;
  10. import javax.annotation.Nullable;
  11. @CheckReturnValue
  12. @GwtCompatible
  13. public final class Strings {
  14.    private Strings() {
  15.    }
  16.    public static String nullToEmpty(@Nullable String string) {
  17.        return string == null?"":string;
  18.    }
  19.    @Nullable
  20.    public static String emptyToNull(@Nullable String string) {
  21.        return isNullOrEmpty(string)?null:string;
  22.    }
  23.    public static boolean isNullOrEmpty(@Nullable String string) {
  24.        return string == null || string.length() == 0;
  25.    }
  26.    public static String padStart(String string, int minLength, char padChar) {
  27.        Preconditions.checkNotNull(string);
  28.        if(string.length() >= minLength) {
  29.            return string;
  30.        } else {
  31.            StringBuilder sb = new StringBuilder(minLength);
  32.            for(int i = string.length(); i < minLength; ++i) {
  33.                sb.append(padChar);
  34.            }
  35.            sb.append(string);
  36.            return sb.toString();
  37.        }
  38.    }
  39.    public static String padEnd(String string, int minLength, char padChar) {
  40.        Preconditions.checkNotNull(string);
  41.        if(string.length() >= minLength) {
  42.            return string;
  43.        } else {
  44.            StringBuilder sb = new StringBuilder(minLength);
  45.            sb.append(string);
  46.            for(int i = string.length(); i < minLength; ++i) {
  47.                sb.append(padChar);
  48.            }
  49.            return sb.toString();
  50.        }
  51.    }
  52.    public static String repeat(String string, int count) {
  53.        Preconditions.checkNotNull(string);
  54.        if(count <= 1) {
  55.            Preconditions.checkArgument(count >= 0, "invalid count: %s", new Object[]{Integer.valueOf(count)});
  56.            return count == 0?"":string;
  57.        } else {
  58.            int len = string.length();
  59.            long longSize = (long)len * (long)count;
  60.            int size = (int)longSize;
  61.            if((long)size != longSize) {
  62.                throw new ArrayIndexOutOfBoundsException("Required array size too large: " + longSize);
  63.            } else {
  64.                char[] array = new char[size];
  65.                string.getChars(0, len, array, 0);
  66.                int n;
  67.                for(n = len; n < size - n; n <<= 1) {
  68.                    System.arraycopy(array, 0, array, n, n);
  69.                }
  70.                System.arraycopy(array, 0, array, n, size - n);
  71.                return new String(array);
  72.            }
  73.        }
  74.    }
  75.    public static String commonPrefix(CharSequence a, CharSequence b) {
  76.        Preconditions.checkNotNull(a);
  77.        Preconditions.checkNotNull(b);
  78.        int maxPrefixLength = Math.min(a.length(), b.length());
  79.        int p;
  80.        for(p = 0; p < maxPrefixLength && a.charAt(p) == b.charAt(p); ++p) {
  81.            ;
  82.        }
  83.        if(validSurrogatePairAt(a, p - 1) || validSurrogatePairAt(b, p - 1)) {
  84.            --p;
  85.        }
  86.        return a.subSequence(0, p).toString();
  87.    }
  88.    public static String commonSuffix(CharSequence a, CharSequence b) {
  89.        Preconditions.checkNotNull(a);
  90.        Preconditions.checkNotNull(b);
  91.        int maxSuffixLength = Math.min(a.length(), b.length());
  92.        int s;
  93.        for(s = 0; s < maxSuffixLength && a.charAt(a.length() - s - 1) == b.charAt(b.length() - s - 1); ++s) {
  94.            ;
  95.        }
  96.        if(validSurrogatePairAt(a, a.length() - s - 1) || validSurrogatePairAt(b, b.length() - s - 1)) {
  97.            --s;
  98.        }
  99.        return a.subSequence(a.length() - s, a.length()).toString();
  100.    }
  101.    @VisibleForTesting
  102.    static boolean validSurrogatePairAt(CharSequence string, int index) {
  103.        return index >= 0 && index <= string.length() - 2 && Character.isHighSurrogate(string.charAt(index)) && Character.isLowSurrogate(string.charAt(index + 1));
  104.    }
  105. }

现在我们具体看一下每个方法具体含义以及使用方式:

(1)私有构造器

  1. private Strings() {}

静态方式使用strings,所以不需要使用权限为public的构造器,设置为private更合理。

(2)isNullOrEmpty

  1. public static boolean isNullOrEmpty(@Nullable String string) {
  2.     return string == null || string.length() == 0;
  3. }

@Nullable 表示该参数变量可以为空。

含义:如果传入的参数string变量为null或者为空,则返回true,否则返回false。

(3)nullToEmpty

  1. public static String nullToEmpty(@Nullable String string) {
  2.     return string == null?"":string;
  3. }

含义:如果传入的参数string变量不为null,则返回该string变量,否则返回空字符串。使用此方法的目的是使null转换为空字符串。

(4)emptyToNull(@Nullable String string)

  1. @Nullable
  2. public static String emptyToNull(@Nullable String string) {
  3.    return isNullOrEmpty(string) ? null : string;
  4. }

含义:

如果传入的参数string变量不为空或者null,则返回该string变量,否则返回null。使用此方法的目的是使空字符串转换为null。

(5)padStart(String string,int minLength,char padChar) 

含义:

从开始位置使用padChar传入的字符补全字符串,长度至少为minLength。即如果如果给定的字符串的长度已经大于minLength,则不用补全字符串。

举例:

  1. // 使用字符0从开始位置填充补全字符串,长度至少为5
  2. String padStartResult = Strings.padStart("123", 5, '0');
  3. System.out.println("padStartResult is " + padStartResult);
  4. // 使用字符0从开始位置填充补全字符串,长度至少为3
  5. String padStartResult2 = Strings.padStart("12345", 3, '0');
  6. System.out.println("padStartResult is " + padStartResult2);

结果:

  1. padStartResult is 00123
  2. padStartResult is 12345

源码分析:

  1.    /**
  2.     *
  3.     * @param string 待补全字符串
  4.     * @param minLength 补全后的长度至少为minLength
  5.     * @param padChar 填充的字符
  6.     * @return 返回补全后的字符串
  7.     */
  8.    public static String padStart(String string, int minLength, char padChar) {
  9.        // 先决条件 检查是否为null
  10.        Preconditions.checkNotNull(string);
  11.        // 如果字符串本身长度大于minLength(最低要求)则直接返回
  12.        if(string.length() >= minLength) {
  13.            return string;
  14.        }
  15.        // 如果不够minLength,则需要填充
  16.        else {
  17.            // 开辟minLength大小空间
  18.            StringBuilder sb = new StringBuilder(minLength);
  19.            // 使用padChar字符在字符串开始填充直至达到minLength
  20.            for(int i = string.length(); i < minLength; ++i) {
  21.                sb.append(padChar);
  22.            }
  23.            sb.append(string);
  24.            return sb.toString();
  25.        }
  26.    }

注意:待补全字符串string不能为null,否则抛出异常

(6)padEnd(String string,int minLength,char padChar) 

含义:

从字符串后使用padChar字符填充字符串,使长度达到minLength。如果如果给定的字符串的长度已经大于等于minLength,则不用补全字符串。

举例:

  1. // 使用字符0从字符串末尾填充补全字符串,长度不足6进行补全
  2. String padEndResult = Strings.padEnd("123", 6, '0');
  3. System.out.println("padEndResult is " + padEndResult);
  4. // 使用字符0从字符串末尾填充补全字符串,长度至不足3进行补全
  5. String padEndResult2 = Strings.padEnd("12345", 4, '0');
  6. System.out.println("padEndResult is " + padEndResult2);

结果:

  1. padEndResult is 123000
  2. padEndResult is 12345

源码分析:

  1.    /**
  2.     *
  3.     * @param string 待补全字符串
  4.     * @param minLength 补全后的长度至少为minLength
  5.     * @param padChar 填充字符
  6.     * @return 返回补全后的字符串
  7.     */
  8.    public static String padEnd(String string, int minLength, char padChar) {
  9.        // 先决条件 检查是否为null
  10.        Preconditions.checkNotNull(string);
  11.        // 如果字符串本身长度大于等于minLength(最低要求)则直接返回
  12.        if(string.length() >= minLength) {
  13.            return string;
  14.        }
  15.        // 如果不够minLength,则需要填充
  16.        else {
  17.            // 开辟minLength大小空间
  18.            StringBuilder sb = new StringBuilder(minLength);
  19.            sb.append(string);
  20.            // 使用padChar字符在字符串后填充直至字符串长度达到minLength
  21.            for(int i = string.length(); i < minLength; ++i) {
  22.                sb.append(padChar);
  23.            }
  24.            return sb.toString();
  25.        }
  26.    }

(7)repeat(String string,int count)

含义:


举例:

  1. String repeatStr = Strings.repeat("123",3);
  2. System.out.println("repeatStr is " + repeatStr);
  3. String repeatStr2 = Strings.repeat("12",0);
  4. System.out.println("repeatStr is " + repeatStr2);

结果:

  1. repeatStr is 123123123
  2. repeatStr is

源码分析:

  1. /**
  2.     *
  3.     * @param string 待重复字符串
  4.     * @param count 重复次数
  5.     * @return
  6.     */
  7.    public static String repeat(String string, int count) {
  8.        // 先决条件 检查是否为null
  9.        Preconditions.checkNotNull(string);
  10.        // 重复次数小于等于1
  11.        if(count <= 1) {
  12.            // 重复次数必须大于等于0 小于0报非法参数异常
  13.            Preconditions.checkArgument(count >= 0, "invalid count: %s", new Object[]{Integer.valueOf(count)});
  14.            // 如果重复次数为0则返回空字符串
  15.            return count == 0?"":string;
  16.        }
  17.        // 重复次数大于1
  18.        else {
  19.            int len = string.length();
  20.            // 计算重复后的大小
  21.            long longSize = (long)len * (long)count;
  22.            // long 防止溢出
  23.            int size = (int)longSize;
  24.            // 判断是否溢出 抛出数组下标越界异常
  25.            if((long)size != longSize) {
  26.                throw new ArrayIndexOutOfBoundsException("Required array size too large: " + longSize);
  27.            }
  28.            else {
  29.                // 开辟size大小空间
  30.                char[] array = new char[size];
  31.                // 把这个字符串中的[0,len)区间字符复制到目标字符数组[0,len)区间
  32.                string.getChars(0, len, array, 0);
  33.                int n;
  34.                for(n = len; n < size - n; n <<= 1) {
  35.                    // 复制源数组中[0,n)区间数据到目标数组[n,2n)区间中
  36.                    System.arraycopy(array, 0, array, n, n);
  37.                }
  38.                // 复制源数组中[0,size - n)区间数据到目标数组[n,size)区间中
  39.                System.arraycopy(array, 0, array, n, size - n);
  40.                return new String(array);
  41.            }
  42.        }
  43.    }

备注:

  1. public void getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin)

java.lang.String.getChars() 方法从这个字符串中的字符复制到目标字符数组。要复制的第一个字符在索引srcBegin处,被复制的最后一个字符是在srcEnd-1位置,即要复制的字符区间为[srcBegin,srcEnd)。字符被复制到子数组的dstBegin位置。

  1. public static void arraycopy(Object src, int srcPos, Object dest, int destPos, int length)

复制指定的源容器数据到目标容器,从源容器指定的位置开始,复制到目标容器的指定位置。src容器的[srcPos,srcPos+len)区间数据复制到目标容器的[destPos,destPos+len)区间。


注意:count必须大于等于0,否则报非法参数异常。

(8)validSurrogatePairAt(CharSequence string, int index)

含义:

判断最后两个字符是不是合法的“Java 平台增补字符”

源码分析:

  1.    @VisibleForTesting
  2.    static boolean validSurrogatePairAt(CharSequence string, int index) {
  3.        return index >= 0 && index <= string.length() - 2 && Character.isHighSurrogate(string.charAt(index)) && Character.isLowSurrogate(string.charAt(index + 1));
  4.    }

Character.isHighSurrogate   确定给定char值是Unicode高代理项代码单元(也称为高级代理项代码单元)。这个值并不代表字符本身,而是在UTF-16编码的补充的字符的表示被使用。

Character.isLowSurrogate  确定给定char值是否为一个Unicode低代理项代码单元(也称为尾部代理项代码单元)。这些值并不代表本身的字符,但用于表示增补字符的UTF-16编码。

(9)commonPrefix(CharSequence a, CharSequence b)

含义:

获得两个字符串相同的前缀

举例:

  1. // 相同前缀
  2. String a = "com.qunar.exercise.exception";
  3. String b = "com.qunar.exercise.log";
  4. String ourCommonPrefix = Strings.commonPrefix(a,b);
  5. System.out.println("a,b common prefix is " + ourCommonPrefix);

结果:

  1. a,b common prefix is com.qunar.exercise.

源码分析:

  1. /**
  2.     *
  3.     * @param a 字符序列a
  4.     * @param b 字符序列b
  5.     * @return 公共前缀
  6.     */
  7. public static String commonPrefix(CharSequence a, CharSequence b) {
  8.        // Preconditions.checkNotNull 先决条件 判断是否为null
  9.        checkNotNull(a);
  10.        checkNotNull(b);
  11.        // 两者最小长度(公共前缀不超过两者的最小长度)
  12.        int maxPrefixLength = Math.min(a.length(), b.length());
  13.        // 从字符串开始比较是否相同直至失败
  14.        int p = 0;
  15.        while (p < maxPrefixLength && a.charAt(p) == b.charAt(p)) {
  16.            p++;
  17.        }
  18.        // 判断最后两个字符是不是合法的“Java 平台增补字符”
  19.        if (validSurrogatePairAt(a, p - 1) || validSurrogatePairAt(b, p - 1)) {
  20.            p--;
  21.        }
  22.        return a.subSequence(0, p).toString();
  23. }

(10)commonSuffix(CharSequence a, CharSequence b)

含义:

获得两个字符串相同的后缀

举例:

      // 相同后缀
  1. String c = "com.google.Hello";
  2. String d = "com.jd.Hello";
  3. String ourSuffix = Strings.commonSuffix(c,d);
  4. System.out.println("c,d common suffix is " + ourSuffix);

结果:

  1. c,d common suffix is .Hello

源码分析:

  1. /**
  2.     *
  3.     * @param a 字符序列a
  4.     * @param b 字符序列b
  5.     * @return 公共后缀
  6.     */
  7. public static String commonSuffix(CharSequence a, CharSequence b) {
  8.        // Preconditions.checkNotNull 先决条件 判断是否为null
  9.        Preconditions.checkNotNull(a);
  10.        Preconditions.checkNotNull(b);
  11.        // 两者最小长度(公共后缀不超过两者的最小长度)
  12.        int maxSuffixLength = Math.min(a.length(), b.length());
  13.        int s;
  14.        // 从字符串末尾开始比较,查看是否相同直至失败
  15.        for(s = 0; s < maxSuffixLength && a.charAt(a.length() - s - 1) == b.charAt(b.length() - s - 1); ++s) {
  16.            ;
  17.        }
  18.        // 判断最后两个字符是不是合法的“Java 平台增补字符” ?
  19.        if(validSurrogatePairAt(a, a.length() - s - 1) || validSurrogatePairAt(b, b.length() - s - 1)) {
  20.            --s;
  21.        }
  22.        return a.subSequence(a.length() - s, a.length()).toString();
  23. }



查看评论

Java.lang.Character类学习

题目:输入一行字符,分别统计出其中英文字母、空格、数字和其它字符的个数。    通过上述的问题来学习下Character类。Character将一个char基本数据类型封装在类中。这个类中只有一...
  • cherish_xmm
  • cherish_xmm
  • 2015-11-12 22:14:11
  • 2084

XMPP 服务器 Openfire 的 Emoji 支持问题(进行部分修改)

在为领航信息开发 eMessage 支持的时候,我们曾使用著名的开源 XMPP 服务器软件 Openfire。但在使用中遇到了几个问题,并通过修改源代码将这些问题解决掉了。接下来的几篇文章,我会介绍一...
  • ldwtill
  • ldwtill
  • 2014-04-08 21:53:51
  • 3072

Guava源码学习(1)--Strings.Repeat

最近学Guava库看Strings这个增强String功能的工具包的时候看到了一个函数Repeat,接受两个函数,一个字符串用于被重复,count用来确认重复次数,返回重复后的字符串。于是我就想我会怎...
  • llpookk
  • llpookk
  • 2015-06-30 21:25:58
  • 859

Base64 加密、解密的实现

加密: import java.io.UnsupportedEncodingException; import org.apache.commons.codec.binary.Base64; ...
  • Soul_Programmer_Swh
  • Soul_Programmer_Swh
  • 2018-02-01 15:08:27
  • 16

字符串反转及性能测试

方法一: 创建一个临时字符串temp, 通过charAt方法倒序获取字符串的字符。 String temp = ""; String str = "我是中国人"; int length = str....
  • qianshangding0708
  • qianshangding0708
  • 2015-11-25 21:31:12
  • 1329

强大的GUAVA之Strings

Guava 中文是石榴的意思,该项目是 Google 的一个开源项目,包含许多 Google 核心的 Java 常用库。 目前主要包含: com.google.common.annot...
  • zxc406924714
  • zxc406924714
  • 2014-03-19 10:47:52
  • 1795

Strings类的简单使用-代码优雅之道Guava(一)

前言        前边已经对Guava类库做了简单介绍(博文:Java代码优雅之道-Guava(有相关jar包下载)),下面就简单介绍一个Strings工具类的使用,学会灵活使用Strings工具,...
  • chenleixing
  • chenleixing
  • 2015-03-29 23:02:27
  • 9653

Java 源码分析(五)

在看StringBuilder和StringBuffer前,我们需要看一下AbstractStringBuilder类,因为前面两个类都继承于此。   1)value成员和count成员 cha...
  • qq_31697201
  • qq_31697201
  • 2017-10-11 15:30:13
  • 361

共同学习Java源代码--常用工具类--AbstractStringBuilder(九)

public int indexOf(String str) {         return indexOf(str, 0);     }     public int indexOf(Str...
  • ccdust
  • ccdust
  • 2016-04-28 18:49:52
  • 220

基于MVVM的知乎日报应用源码

使用data binding , dagger2 , retrofit2和rxjava实现的,基于MVVM的知乎日报APP 运行效果:   使用说明: 项目结构 android d...
  • qq_16542455
  • qq_16542455
  • 2016-05-13 09:38:03
  • 234
    个人资料
    专栏达人 持之以恒
    等级:
    访问量: 159万+
    积分: 2万+
    排名: 371
    博客专栏
    最新评论