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

Java 将'IntStream'打印为'String'的最简单方法`,java,java-8,java-stream,Java,Java 8,Java Stream,使用Java-8,我可以使用chars或codePoints方法轻松地将字符串(或任何CharSequence)视为IntStream IntStream chars = "Hello world.".codePoints(); 然后我可以操纵流的内容 IntStream stars = chars.map(c -> c == ' ' ? ' ': '*'); 我一直在寻找一个整洁的方式来打印结果,我甚至找不到一个简单的方式。如何将ints流放回可以像打印字符串一样打印的表单中 从上面

使用Java-8,我可以使用
chars
codePoints
方法轻松地将
字符串(或任何
CharSequence
)视为
IntStream

IntStream chars = "Hello world.".codePoints();
然后我可以操纵流的内容

IntStream stars = chars.map(c -> c == ' ' ? ' ': '*');
我一直在寻找一个整洁的方式来打印结果,我甚至找不到一个简单的方式。如何将
int
s流放回可以像打印
字符串一样打印的表单中

从上面的
stars
我希望打印

***** ******

但是,
“你好,世界。”.replaceAll(“[^]”),“*”
更简单。并非所有产品都能从lambdas中获益。

效率稍低,但更简洁地解决了Holger的问题:

String result=“你好,世界。”
.codePoints()
.mapToObj(c->c==“”?:“*”)
.collect(收集器.joining());

Collectors.joining()
在内部使用
StringBuilder
,至少在。

其他答案说明如何将字符串流收集到单个字符串中,以及如何从
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);
}
publicstaticvoidmain(字符串[]args){
字符串s=“abcacb”.codePoints()
.filter(通道->通道!=“b”)
.boxed()
.collect(charsToString());
System.out.println(“s:+s);//打印“s:acac”
}
公共静态收集器charsToString(){
返回收集器(
StringBuilder::新建,
StringBuilder::appendCodePoint,
StringBuilder::append,
StringBuilder::toString);
}
标准库中没有这样的东西,这有点令人惊讶

这种方法的一个缺点是需要对字符进行装箱,因为
IntStream
接口不能与收集器一起工作


一个尚未解决的难题是实用方法的名称。收集器实用程序方法的约定是调用它们
toXXX
,但是
toString
已被采用。

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

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

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

public static String stars(String t) {
    StringBuilder sb = new StringBuilder(t.length());
    t.codePoints().map(c -> c == ' ' ? ' ' : '*').forEach(sb::appendCodePoint);
    return sb.toString();
}
有时short和concrete不一样,我认为任何人都不必怀疑上面的函数是如何运行的


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

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

public static String stars(String t) {
    return t.codePoints().map(c -> c == ' ' ? ' ': '*').mapToObj(i -> new String(new int[] { i }, 0, 1)).collect(Collectors.joining());
}
它执行与相同的版本,但始终使用流媒体。显然需要一些函数将单个代码点转换为字符串:

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);
}
这将这些函数放置在类中,当然是星号。

您可以执行以下操作:

chars.mapToObj(c -> c == ' ' ?  " ": "*").collect(joining());
另一个例子:

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



我的方法是使用reduce。要获得每个字符的*和每个空格的空格,它将如下所示

    String hello = "hello world";
    String result = hello.chars()
        .map(val -> (val == ' ') ?  ' ' : '*')
        .mapToObj(val -> String.valueOf((char) val))
        .reduce("",(s1, s2) -> s1+s2);
关键是要对整数执行任何操作,而不是将其强制转换为字符,然后将其映射到字符串,然后将其连接起来,您可以使用reduce或Collectors.joining()

这怎么样

System.out.println(stars.mapToObj(c->String.format(“%c”,c)).collect(
连接());
或
字符串s=stars.mapToObj(c->String.format(“%c”,c)).reduce(“,
(a,b)->a+b);

这对我很有用。

我对此感到高兴。我理解你关于过度使用lambdas的观点——我的例子只是一个例子。我知道,我无法抗拒。更复杂的字符转换甚至可以从并行执行中受益……这一点都不简单。这些东西应该从Java中删除,并变得更加复杂simple@GeorgiosPligoropoulos这里不是讨论Java应该是什么或不是什么的合适地方。@GeorgiosPligoropoulos Stackoverflow仍然不是这样讨论的合适地方。顺便说一下,这是answer开发的一个阶段。欢迎大家发表意见。很好!谢谢-当然有点整洁。为什么效率会低一些?@MaartenBodewes,因为它会在加入字符之前将每个字符转换为字符串。啊,好的。您认为我的解决方案如何:我不经常使用流。
customTag=secureRandom.ints(9,0,chrs.length()).mapToObj(I->chrs.charAt(I)).collector(Collectors.joining())产生IDE编译错误
方法collect(CollectorMy解决方案不收集字符串,但收集
int
s。事实上,它使用的操作与您的解决方案几乎完全相同。唯一的区别是它不需要装箱,正确处理补充代码点,并且更紧凑。没有用于此目的的内置收集器的原因正是disadvan您命名的阶段:由于
IntStream
不支持
Collector
s,因此需要装箱。另一方面,如果您不介意装箱开销,使用
Collector.joining()的解决方案
就足够了。@霍尔格:在使用
收集器时。加入
必须将字符包装成字符串,这稍微贵一点,并且不能清楚地表达意图。在使用int-streams时,不能使用收集器。这为收集器使用盒装字符的方法提供了一些理由。这也可能会导致是个好主意
chars.mapToObj(i -> String.valueOf((char) i)).collect(Collectors.joining()));
"abc".chars().mapToObj(i -> "" + (char) i)).collect(Collectors.joining()));
    String hello = "hello world";
    String result = hello.chars()
        .map(val -> (val == ' ') ?  ' ' : '*')
        .mapToObj(val -> String.valueOf((char) val))
        .reduce("",(s1, s2) -> s1+s2);
  IntStream charStream = "hello".chars();
  charStream.mapToObj(c -> (char)c).forEach(System.out::println);