将`IntStream`打印为`String`的最简单方法

Old*_*eon 43 java java-8 java-stream

与Java-8 I可以很容易地处理一个String(或任何CharSequence),为IntStream使用任一charscodePoints方法.

IntStream chars = "Hello world.".codePoints();
Run Code Online (Sandbox Code Playgroud)

然后我可以操纵流的内容

IntStream stars = chars.map(c -> c == ' ' ? ' ': '*');
Run Code Online (Sandbox Code Playgroud)

我一直在寻找一种整洁的方式来打印结果,我甚至找不到一个简单的方法.如何将这个ints流放回一个可以像我一样打印的形式String.

从上面stars我希望打印

***** ******
Run Code Online (Sandbox Code Playgroud)

Hol*_*ger 35

String result = "Hello world."
  .codePoints()
//.parallel()  // uncomment this line for large strings
  .map(c -> c == ' ' ? ' ': '*')
  .collect(StringBuilder::new,
           StringBuilder::appendCodePoint, StringBuilder::append)
  .toString();
Run Code Online (Sandbox Code Playgroud)

但是,"Hello world.".replaceAll("[^ ]", "*")更简单.并非一切都受益于lambdas.

  • 我知道,我无法抗拒.更复杂的角色转换甚至可以从并行执行中受益...... (5认同)
  • @GeorgiosPligoropoulos Stackoverflow 仍然不是进行此类讨论的正确场所 (3认同)
  • @GeorgiosPligoropoulos 这不是讨论 Java 应该是什么或不应该是什么的合适地方。 (2认同)

Luk*_*tor 19

Holger的效率稍低但更简洁的解决方案:

String result = "Hello world."
    .codePoints()
    .mapToObj(c -> c == ' ' ? " ": "*")
    .collect(Collectors.joining());
Run Code Online (Sandbox Code Playgroud)

Collectors.joining()内部使用StringBuilder,至少在OpenJDK源中使用.


Lii*_*Lii 6

其他答案显示如何将字符串流收集到单个字符串以及如何从中收集字符IntStream.此答案显示如何在字符流上使用自定义收集器.

如果你想将一个int流收集到一个字符串中,我认为最干净,最通用的解决方案是创建一个返回收集器的静态实用程序方法.然后你可以Stream.collect像往常一样使用这个方法.

可以像这样实现和使用此实用程序:

public static void main(String[] args){
    String s = "abcacb".codePoints()
        .filter(ch -> ch != 'b')
        .boxed()
        .collect(charsToString());

    System.out.println("s: " + s); // Prints "s: acac"
}

public static Collector<Integer, ?, String> charsToString() {
    return Collector.of(
        StringBuilder::new,
        StringBuilder::appendCodePoint,
        StringBuilder::append,
        StringBuilder::toString);
}
Run Code Online (Sandbox Code Playgroud)

标准库中没有类似的东西,这有点令人惊讶.

这种方法的一个缺点是它需要将字符装箱,因为IntStream接口不能与收集器一起使用.

一个未解决的难题是应该命名实用程序方法.收集器实用程序方法的约定是调用它们toXXX,但toString已经采用.

  • 我的解决方案*不*收集字符串,而是收集“int”。事实上,它使用与您的解决方案几乎完全相同的操作。唯一的区别是它不需要装箱、正确处理补充代码点并且更紧凑。没有用于此目的的内置收集器的原因正是您所指出的缺点:由于“IntStream”不支持“Collector”,因此需要装箱。另一方面,如果您不介意装箱开销,那么使用“Collectors.joining()”的解决方案就足够了。 (2认同)