Java8流:IntStream到字符串
在Java8StreamsAPI中,对任何Java8流:IntStream到字符串,java,java-8,java-stream,Java,Java 8,Java Stream,在Java8StreamsAPI中,对任何String对象调用chars()将返回一个包含所有字符的IntStream对象 将返回的IntStream对象转换回字符串的正确方法是什么?调用toArray()会给我一个int[],这是任何字符串构造函数都不接受的。您可以使用toArray(),然后使用构造函数。这并不完全令人满意,因为指定了chars()返回UTF-16代码单元,基本上: 返回一个int zero流,扩展此序列中的字符值。映射到代理代码点的任何字符都会通过unexported传递
String
对象调用chars()
将返回一个包含所有字符的IntStream
对象
将返回的IntStream
对象转换回字符串的正确方法是什么?调用toArray()
会给我一个int[]
,这是任何字符串构造函数都不接受的。您可以使用toArray()
,然后使用构造函数。这并不完全令人满意,因为指定了chars()
返回UTF-16代码单元,基本上:
返回一个int zero流,扩展此序列中的字符值。映射到代理代码点的任何字符都会通过unexported传递
改用将更符合此构造函数,它需要代码点而不是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建议的专用采集器效率不高,因为它是装箱式的,所以您应该使用这个三参数结构(感谢@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);
使用StringBuilder
的appendCodePoint
方法也可以做到这一点
IntStream in = "Convert me to a String".codePoints();
String intStreamToString = in.collect(StringBuilder::new,
StringBuilder::appendCodePoint, StringBuilder::append)
.toString();
System.out.println(intStreamToString);
哪个类包含chars()
方法?该方法在CharSequence
接口中定义,该接口由String
实现。使用codePoints()
而不是chars()
似乎更安全,尽管这对我来说并不重要,因为我只是在ASCII范围内工作。不管怎样,谢谢。我确实考虑过这个方向,但它看起来太复杂了。不过,我有一个简短的问题。为什么第三个参数(sb1,sb2)->{}
?这到底意味着什么?这个零件根本不用吗?也许它只在使用并行流时才相关?它是组合器,“一个接受两个部分结果并合并它们的函数。”。使用“顺序”时不使用它。然而,我的示例很难看,因此我对其进行了改进,删除了关于并行支持的警告IntStream
不支持专用的Collector
s,因此使用三个argcollect
方法是唯一的选择(除非你想框选每个int
。@holger你说得对!编辑了我的答案是的,但这一个也有代码单元/代码点不匹配的问题@jon skeet指出。chars()
返回代码单元流,而appendCodePoint
希望得到代码点,顾名思义。问题是StringBuilder对象会创建多次。@不,只会创建一个StringBuilder
,请参见@cdalxndr您说得对!我很困惑。在TerminalOp中只调用了一次。没有想过将其与IO库结合。谢谢。@nullstein,正如我的版本所示,它也可以作为收藏家来写,尽管我怀疑它是否更容易阅读。好的一面是,它确实具有更好的引用透明度,因为副作用对流用户是隐藏的。不过,这最终与StringBuilder的答案类似。请注意,StringWriter是StringBuffer(StringBuilder的同步版本)的包装器,因此(相对而言)比使用StringBuilder慢得多