Java8中StringJoiner的底层原理及使用用法(附源码)

Java 8 提供了一种新的字符串操作方式 StringJoiner ,相较上文介绍的字符串拼接10种方法, StringJoiner 是更为高级一些的用法了。

import java.util.StringJoiner;

public class Test {
    public static void main(String[] args) {

        StringJoiner joiner;

    }
}

StringJoiner 的操作和其他字符串类型不同,它的包来自于 java.util.StringJoiner 。

根据常规,通常 java.util 包下的内容可以理解为一个工具类。

通过 IDEA 分析,我们可以看到在这个类中提供的如下方法操作。

Java8中StringJoiner的底层原理及使用用法(附源码)

StringJoiner 的用法

接下来,我们就通过测试类的操作,来详解 StringJoiner 的用法。

先来创建一个测试类,示例代码:

public class Test {
    public static void main(String[] args) {
        StringJoiner stringJoiner = new StringJoiner("Hello");

        stringJoiner.add("World");
        stringJoiner.add("架构师面试");
        System.out.println(stringJoiner.toString());

        StringJoiner stringJoiner1 = new StringJoiner(":","[","]");

        stringJoiner1.add("Hello").add("World").add("字符串操作");
        System.out.println(stringJoiner1.toString());
    }
}

结果:

Java8中StringJoiner的底层原理及使用用法(附源码)

在 StringJoiner 类中,提供了两个构造函数,有 5 个公有的方法。其中,add 方法、toString 方法是使用最多的两种方法。

接下来,我们来了解下 add 方法的实现原理。

add 原理

我们来看 add() 方法的源码:

public StringJoiner add(CharSequence newElement) {
      prepareBuilder().append(newElement);
      return this;
  }

 private StringBuilder prepareBuilder() {
      if (value != null) {
          value.append(delimiter);
      } else {
          value = new StringBuilder().append(prefix);
      }
      return value;
  }

可见,add() 方法使用的是 StringBuilder 来进行字符串操作,并且使用 StringJoiner 和直接使用 StringBuilder 是一样的。

但是,为什么还要新增加这样一个类操作?

StringJoiner 分析

如果要将一个数组中的所有对象、拼接成一个大的字符串对象,应该怎样实现拼接?

第1种方法,采用循环数组对象、使用 StringBuilder 来进行拼接。

StringBuilder builder = new StringBuilder();

if (!list.isEmpty()) {
    builder.append(list.get(0));
    for (int i = 1, n = list.size(); i < n; i++) {
        builder.append(",").append(list.get(i));
    }
}
builder.toString();

第2种方法,使用 Java8 中提供的 lambda 表达式来进行拼接。

list.stream().reduce(new StringBuilder(), (sb, s) -> sb.append(s).append(','), StringBuilder::append).toString();

第3种方法,在循环中使用 + 的方式来进行拼接(不推荐)。

以认上3种方法,都能实现上面说的拼接,但由于涉及到循环,整体的效率都不是太高。

有没有可以提高效率的、更好的选择呢?

Java 8 中提供的字符串操作方式 StringJoiner ,就能在实现拼接的同时提高效率。

首先,我们来分析一个类 Collectors 。

java.util.stream.Collectors 可以实现各种有用的缩减操作的 Collector 。例如:将元素累积到集合中,根据各种标准汇总元素等。

通过这个类中的 joining() 方法:

public static Collector<CharSequence, ?, String> joining() {
    return new CollectorImpl<CharSequence, StringBuilder, String>(
            StringBuilder::new, StringBuilder::append,
            (r1, r2) -> { r1.append(r2); return r1; },
            StringBuilder::toString, CH_NOID);
}

 public static Collector<CharSequence, ?, String> joining(CharSequence delimiter,
                                                         CharSequence prefix,
                                                         CharSequence suffix) {
    return new CollectorImpl<>(
            () -> new StringJoiner(delimiter, prefix, suffix),
            StringJoiner::add, StringJoiner::merge,
            StringJoiner::toString, CH_NOID);
}

将这个方法与 stream() 方法进行结合,也就是在 Java8 中提供的一些高级用法。

list.stream().collect(Collectors.joining(":"))

可见,在 joining() 方法中,既使用了 StringBuilder ,又使用了 StringJoiner ,来提高效率。

总结

本文主要介绍了Java 8 中的StringJoiner 的高级用法,以及几种方法的使用比较。

在实际研发中,还是要围绕提升开发效率为目的的,针对不同的场景、选择合适的方法。

0 条回复 A文章作者 M管理员
    暂无讨论,说说你的看法吧