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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/20266422/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 00:42:26  来源:igfitidea点击:

Simplest way to print an `IntStream` as a `String`

javajava-8java-stream

提问by OldCurmudgeon

With Java-8 I can easily treat a String(or any CharSequence) as an IntStreamusing either the charsor the codePointsmethod.

使用 Java-8,我可以轻松地将 a String(或任何CharSequence)视为IntStream使用 thechars或 thecodePoints方法。

IntStream chars = "Hello world.".codePoints();

I can then manipulate the contents of the stream

然后我可以操作流的内容

IntStream stars = chars.map(c -> c == ' ' ? ' ': '*');

I have been hunting for a tidy way to print the results and I cant even find a simple way. How do I put this stream of ints back into a form that can be printed like I can a String.

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

From the above starsI hope to print

从上面stars我希望打印

***** ******

采纳答案by Holger

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

But still, "Hello world.".replaceAll("[^ ]", "*")is simpler. Not everything benefits from lambdas.

不过,"Hello world.".replaceAll("[^ ]", "*")还是比较简单的。并非一切都从 lambda 中受益。

回答by Lukasz Wiktor

A bit less efficient but more concise solution to Holger's:

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

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

Collectors.joining()internally uses StringBuilder, at least in OpenJDK sources.

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

回答by Lii

Other answers show how to collect a stream of strings into a single string and how to collect characters from an IntStream. This answer shows how to use a custom collector on a stream of characters.

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

If you want to collect a stream of ints into a string, I think the cleanest and most general solution is to create a static utility method that returns a collector. Then you can use the Stream.collectmethod as usual.

如果你想将一个整数流收集到一个字符串中,我认为最干净和最通用的解决方案是创建一个返回收集器的静态实用程序方法。然后就可以Stream.collect照常使用该方法了。

This utility can be implemented and used like this:

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

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

It's a bit surprising that there isn't something like this in the standard library.

标准库中没有这样的东西,这有点令人惊讶。

One disadvantage of this approach is that it requires the chars to be boxed since the IntStreaminterface does not work with collectors.

这种方法的一个缺点是它需要将字符装箱,因为IntStream接口不适用于收集器。

An unsolved and hard problem is what the utility method should be named. The convention for collector utility methods is to call them toXXX, but toStringis already taken.

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

回答by Master Za'im

You can do it directly with the following code :-

您可以直接使用以下代码进行操作:-

"Hello world".codePoints().forEach(n -> System.out.print(n == ' ' ? ' ':'*'));

回答by Maarten Bodewes

There is a simple answer that is slightly less inclined to doing everything with streaming. Hence it is not a one-liner, but it is probably more efficient and very easy to read:

有一个简单的答案,它不太倾向于使用流媒体做所有事情。因此,它不是单行的,但它可能更高效且易于阅读:

public static String stars(String t) {
    StringBuilder sb = new StringBuilder(t.length());
    t.codePoints().map(c -> c == ' ' ? ' ' : '*').forEach(sb::appendCodePoint);
    return sb.toString();
}

Sometimes short is not the same as concise, I don't think anybody has to wonder how the above function operates.

有时简短不等于简洁,我想没有人会好奇上面的函数是如何运行的。

This solution makes sure that the code points are never converted back to characters. It is therefore somewhat more generic than some other solutions listed here.

此解决方案确保代码点永远不会转换回字符。因此,它比此处列出的其他一些解决方案更通用。

回答by Maarten Bodewes

If we must, we can make a one-liner this extremely ugly way:

如果必须的话,我们可以用这种极其丑陋的方式制作单行:

public static String stars(String t) {
    return t.codePoints().map(c -> c == ' ' ? ' ': '*').mapToObj(i -> new String(new int[] { i }, 0, 1)).collect(Collectors.joining());
}

It performs the exact same version as my other answerbut it uses streaming all the way. Some function to convert a single code point to a string is obviously needed:

它执行与我的其他答案完全相同的版本,但它一直使用流媒体。显然需要一些将单个代码点转换为字符串的函数:

public static String stars(String t) {
    return t.codePoints().map(c -> c == ' ' ? ' ': '*').mapToObj(Stars::codePointToString).collect(Collectors.joining());
}

private static String codePointToString(int codePoint) {
    return new String(new int[] { codePoint }, 0, 1);
}

which places these functions in the class Starsof course.

将这些功能放在Stars课程中。

回答by Gayan Weerakutti

You can do:

你可以做:

chars.mapToObj(c -> c == ' ' ?  " ": "*").collect(joining());

Another example:

另一个例子:

The following examples return the original string. But these can be combined with other intermediate operations such as filter().

以下示例返回原始字符串。但是这些可以与其他中间操作相结合,例如filter().

chars.mapToObj(i -> String.valueOf((char) i)).collect(Collectors.joining()));


"abc".chars().mapToObj(i -> "" + (char) i)).collect(Collectors.joining()));

回答by Ahmad

The way I do it is by using reduce. To get *for each character and space for each space it will look like this

我这样做的方法是使用reduce。要获取每个字符的*和每个空格的空格,它看起来像这样

    String hello = "hello world";
    String result = hello.chars()
        .map(val -> (val == ' ') ?  ' ' : '*')
        .mapToObj(val -> String.valueOf((char) val))
        .reduce("",(s1, s2) -> s1+s2);

The point is do whatever you want with the integersthan cast it to charactersthen map it to Stringthen concatenateit, you can use reduceor Collectors.joining()

关键是对整数做任何你想做的事情,而不是将它转换为字符然后将它映射到String然后连接它,你可以使用reduceCollectors.joining()

回答by WJS

How about this.

这个怎么样。

  System.out.println(stars.mapToObj(c -> String.format("%c", c)).collect(
            Collectors.joining()));

  or

  String s = stars.mapToObj(c -> String.format("%c", c)).reduce("",
            (a, b) -> a + b);

回答by foureverhh

  IntStream charStream = "hello".chars();
  charStream.mapToObj(c -> (char)c).forEach(System.out::println);

This works for me.

这对我有用。