问题
In Java 8 streams API, calling chars()
on any String
object returns an IntStream
object containing all the characters.
What would be the correct way to convert the returned IntStream
object back to a String
? Calling toArray()
would give me an int[]
, which is not accepted by any of the String
constructor.
回答1:
You can use toArray()
, then the String(int[], int, int) constructor. This isn't entirely satisfactory as chars()
is specified to return UTF-16 code units, basically:
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.
Using codePoints() instead would be more in-keeping with this constructor, which expects code points rather than UTF-16 code units. Otherwise (with chars
) if your original string does contain surrogate pairs, you may find you get an error - I haven't tried it, but it would make sense.
I don't know of a simple way of doing this without converting to an array first.
回答2:
using StringBuilder
's appendCodePoint
method would do the trick as well,
IntStream in = "Convert me to a String".codePoints();
String intStreamToString = in.collect(StringBuilder::new,
StringBuilder::appendCodePoint, StringBuilder::append)
.toString();
System.out.println(intStreamToString);
回答3:
I am pretty sure there must be many ways to do it, but another way is by using a StringWriter
:
IntStream in = "It was the best of times".chars();
StringWriter sw = new StringWriter();
in.forEach(sw::write);
System.out.println(sw.toString());
This all could also be expressed in a collector as:
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);
回答4:
This is an other idea:
@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);
}
Note that using a dedicated Collector
as proposed by @Lii is not very efficient, because of the boxing so you should use this three argument construct (thanks @holger)
来源:https://stackoverflow.com/questions/28280721/java-8-streams-intstream-to-string