热爱技术,追求卓越
不断求索,精益求精

java内功心决之一成不变,深入理解String及其用法,字符串拼接,字符串拆分

字符串广泛应用 在Java 编程中,在 Java 中字符串属于对象,Java 提供了 String 类来创建和操作字符串。String 类是不可改变的,所以你一旦创建了 String 对象,那它的值就无法改变了,所以这一决为“一成不变”。

创建字符串

创建字符串的最简单方式:

String str = "LoveCTO";

此外,和其它对象一样,可以使用关键字“new”和构造方法来创建String对象:

String str = new String("LoveCTO");

除了这个构造方法外,jdk8中共计提供了16个String的构造方法。

String的核心

String类的核心是其内部的两个成员变量(final修饰的value字符数组和hash):

/** The value is used for character storage. */
private final char value[];

/** Cache the hash code for the string */
private int hash; // Default to 0

String的一成不变的根源在于value字符数组是final的。hash的计算方式如下(String重写了Object的hashCode方法,使用31哈希算法):

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

比较两个字符串是否相同,使用String重写的equals方法:

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

先比较两个字符串对象是否是同一个,再比较是否都是String对象,再看字符串长度是否相同,最后再逐个字符比较。

String常用方法

下面列举几个常用的String类的方法:

//是否以某个字符串作为前缀
public boolean startsWith(String prefix);
//是否以某个字符串作为后缀
public boolean endsWith(String suffix);
//查找子字符串的位置,未查找到返回-1
public int indexOf(String str);
//字符串截取
public String substring(int beginIndex);
//字符串范围截取
public String substring(int beginIndex, int endIndex);
//字符串中是否包含字符序列s
public boolean contains(CharSequence s);
//字符串子串替换
public String replace(CharSequence target, CharSequence replacement);
//告知此字符串是否匹配给定的正则表达式
public boolean matches(String regex);
//使用指定的格式字符串和参数返回一个格式化字符串
public static String format(String format, Object... args);
//使用给定的replacement替换此字符串所有匹配给定的正则表达式的子字符串
public String replaceAll(String regex, String replacement);
//使用给定的replacement替换此字符串匹配给定的正则表达式的第一个子字符串
public String replaceFirst(String regex, String replacement);
//将指定字符串连接到此字符串的结尾
public String concat(String str);
//根据给定正则表达式的匹配拆分此字符串
public String[] split(String regex);

更多可参考 JAVA String API 8 英文JAVA String API 6 中文

字符串拼接大比拼

  1. 直接用“+”号
  2. 使用String的方法concat
  3. 使用StringBuilder的append
  4. 使用StringBuffer的append
  5. 使用String.join(JAVA8)
  6. 使用String.format
  7. 使用StringJoiner(JAVA8)

上面4种拼接方式性能对比:

  1. 无论如何直接用“+”号连接字符串都是最慢的
  2. 在拼接少数字符串(不超过4个)的时候,concat效率是最高的
  3. 多个字符串拼接的时候,StringBuilder/StringBuffer的效率是碾压的
  4. 在不需要考虑线程安全问题的时候,使用StringBuilder的效率比StringBuffer更高
  5. String.join内部使用的是StringJoiner,效率优于“+”和concat,代码更简洁
  6. String.format内部基于StringBuilder,效率优于“+”和concat,类似C语言
  7. StringJoiner内部原理是StringBuilder,java8新特性,可使代码更加简洁

字符串拆分/字符串分割大比拼

  1. String的split
  2. StringTokenizer

StringTokener.hasMoreElement和String.split(String.split是用正则表达式匹配,所以不使用KMP字符串匹配算法)用的都是按顺序遍历的算法,时间复杂度O(m*n),较高。

不过StringTokener是一边按顺序遍历,一边返回每个分组;而Spring.split是全部分组完成,再返回字符串数组。这个区别不大,但是如果我们不需要全部都分组,只需要某个分组的字符串,那么StringTokener性能会好点。

赞(3)
未经允许不得转载:LoveCTO » java内功心决之一成不变,深入理解String及其用法,字符串拼接,字符串拆分

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

热爱技术 追求卓越 精益求精