Java 8 个流:IntStream 到 String

Java 8 Streams: IntStream to String

在 Java 8 个流 API 中,在任何 String 对象上调用 chars() returns 包含所有字符的 IntStream 对象。

将返回的 IntStream 对象转换回 String 的正确方法是什么?调用 toArray() 会给我一个 int[],这不被任何 String 构造函数接受。

可以使用toArray(),然后是String(int[], int, int)构造函数。这并不完全令人满意,因为 chars() 被指定为 return UTF-16 代码单元,基本上:

Returns a stream of int zero-extending the char values from this sequence. Any char which maps to a surrogate code point is passed through uninterpreted.

改用 codePoints() 会更符合此构造函数,它需要代码点而不是 UTF-16 代码单元。否则(使用 chars)如果您的原始字符串 确实 包含代理项对,您可能会发现出现错误 - 我没有尝试过,但它是有道理的。

我不知道有没有先转换为数组的简单方法。

这是另一个想法:

@Test
public void testIntStreamSequential() {
    final String testString = "testmesoftly";
    IntStream is = testString.chars();
    String result = is.collect(
        StringBuilder::new,
        (sb, i) -> sb.append((char)i),
        StringBuilder::append
        ).toString();
    assertEquals(testString, result);
}

@Test
public void testIntStreamParallel() {
    final String testString = "testmesoftly";
    IntStream is = testString.chars();
    String result = is.parallel().collect(
        StringBuilder::new,
        (sb, i) -> sb.append((char)i),
        StringBuilder::append
        ).toString();
    assertEquals(testString, result);
}

请注意,使用@Lii 提议的专用 Collector 效率不高,因为装箱的缘故,因此您应该使用这三个参数构造(感谢@holger)

我很确定一定有很多方法可以做到,但另一种方法是使用 StringWriter:

IntStream in = "It was the best of times".chars();
StringWriter sw = new StringWriter();
in.forEach(sw::write); 
System.out.println(sw.toString());

这一切在收集器中也可以表示为:

IntStream in = "It was the best of times".chars();
String text = in.collect(
    StringWriter::new, 
    StringWriter::write, 
    (swl, swr) -> swl.write(swr.toString())).toString();
System.out.println(text);

使用 StringBuilderappendCodePoint 方法也可以,

IntStream in = "Convert me to a String".codePoints();

String intStreamToString = in.collect(StringBuilder::new,
        StringBuilder::appendCodePoint, StringBuilder::append)
        .toString();

System.out.println(intStreamToString);