Best way to convert Iterable<Character> to String?

泪湿孤枕 提交于 2020-01-01 16:53:08

问题


What's the easiest/fastest way to convert an Iterable<Character> to a String of the characters from the Iterable?

For example, how to convert an Iterable of "A", "B", and "C", to a String "ABC"?

The iter.toString() returns a String "[A, B, C]".


回答1:


5 Versions:

1) Java 8 streams collecting via StringBuilder.append():

public static String streamAppend(Iterable<Character> chars){
    return StreamSupport.stream(chars.spliterator(), true)
                        .collect(
                            StringBuilder::new,
                            StringBuilder::append,
                            StringBuilder::append
                         )
                        .toString();
}

Java 8 Streams collecting via Collectors.joining()

public static String streamJoin(Iterable<Character> chars){
    return StreamSupport.stream(chars.spliterator(), true)
                        .map(Object::toString)
                        .collect(Collectors.joining(""));
}

Pre-Java8-Version using Java 5 for loops:

public static String java7(Iterable<Character> chars) {
    StringBuilder sb = new StringBuilder();
    for (Character c: chars) {
        sb.append(c);
    }
    return sb.toString();
}

Guava version using a Joiner:

public static String guavaJoin(Iterable<Character> chars) {
    return Joiner.on("").join(chars);
}

Java 8 version using Iterable.forEach() and method references:

public static String iterableForEach(Iterable<Character> chars){
    StringBuilder sb = new StringBuilder();
    chars.forEach(sb::append);
    return sb.toString();
}

After the discussions regarding performance, I ran a JMH micro-benchmark to see for myself. The results are obvious, but much more drastic than expected.

Benchmark                           (mode)  (size)          Score    Units
CharsToString.stringJoin     STREAM_APPEND       1    5071451.223 ±  ops/s
CharsToString.stringJoin     STREAM_APPEND       2     481656.870 ±  ops/s
CharsToString.stringJoin     STREAM_APPEND       5     162359.508 ±  ops/s
CharsToString.stringJoin     STREAM_APPEND      10      76910.668 ±  ops/s
CharsToString.stringJoin     STREAM_APPEND      20      49590.249 ±  ops/s
CharsToString.stringJoin     STREAM_APPEND      50      44608.948 ±  ops/s
CharsToString.stringJoin     STREAM_APPEND     100      20940.993 ±  ops/s
CharsToString.stringJoin     STREAM_APPEND     200      29634.118 ±  ops/s
CharsToString.stringJoin     STREAM_APPEND     500      19387.956 ±  ops/s
CharsToString.stringJoin     STREAM_APPEND    1000      17629.508 ±  ops/s
CharsToString.stringJoin       STREAM_JOIN       1    3342341.147 ±  ops/s
CharsToString.stringJoin       STREAM_JOIN       2     279516.584 ±  ops/s
CharsToString.stringJoin       STREAM_JOIN       5     102312.667 ±  ops/s
CharsToString.stringJoin       STREAM_JOIN      10      61759.122 ±  ops/s
CharsToString.stringJoin       STREAM_JOIN      20      34802.386 ±  ops/s
CharsToString.stringJoin       STREAM_JOIN      50      37629.593 ±  ops/s
CharsToString.stringJoin       STREAM_JOIN     100      33493.715 ±  ops/s
CharsToString.stringJoin       STREAM_JOIN     200      26186.986 ±  ops/s
CharsToString.stringJoin       STREAM_JOIN     500      19264.628 ±  ops/s
CharsToString.stringJoin       STREAM_JOIN    1000      14446.396 ±  ops/s
CharsToString.stringJoin        GUAVA_JOIN       1    6570784.907 ±  ops/s
CharsToString.stringJoin        GUAVA_JOIN       2    3821031.465 ±  ops/s
CharsToString.stringJoin        GUAVA_JOIN       5    1574828.190 ±  ops/s
CharsToString.stringJoin        GUAVA_JOIN      10     806057.685 ±  ops/s
CharsToString.stringJoin        GUAVA_JOIN      20     356533.358 ±  ops/s
CharsToString.stringJoin        GUAVA_JOIN      50     156129.534 ±  ops/s
CharsToString.stringJoin        GUAVA_JOIN     100     100195.171 ±  ops/s
CharsToString.stringJoin        GUAVA_JOIN     200      54820.347 ±  ops/s
CharsToString.stringJoin        GUAVA_JOIN     500      20577.137 ±  ops/s
CharsToString.stringJoin        GUAVA_JOIN    1000      11465.704 ±  ops/s
CharsToString.stringJoin  ITERABLE_FOREACH       1   11921819.833 ±  ops/s
CharsToString.stringJoin  ITERABLE_FOREACH       2    7007911.144 ±  ops/s
CharsToString.stringJoin  ITERABLE_FOREACH       5    4415785.561 ±  ops/s
CharsToString.stringJoin  ITERABLE_FOREACH      10    2107685.852 ±  ops/s
CharsToString.stringJoin  ITERABLE_FOREACH      20    1158806.591 ±  ops/s
CharsToString.stringJoin  ITERABLE_FOREACH      50     482412.510 ±  ops/s
CharsToString.stringJoin  ITERABLE_FOREACH     100     265362.511 ±  ops/s
CharsToString.stringJoin  ITERABLE_FOREACH     200     123663.470 ±  ops/s
CharsToString.stringJoin  ITERABLE_FOREACH     500      49238.673 ±  ops/s
CharsToString.stringJoin  ITERABLE_FOREACH    1000      24328.723 ±  ops/s
CharsToString.stringJoin             JAVA7       1    9746936.478 ±  ops/s
CharsToString.stringJoin             JAVA7       2    6431473.785 ±  ops/s
CharsToString.stringJoin             JAVA7       5    2736936.112 ±  ops/s
CharsToString.stringJoin             JAVA7      10    1764353.273 ±  ops/s
CharsToString.stringJoin             JAVA7      20     833322.493 ±  ops/s
CharsToString.stringJoin             JAVA7      50     278354.933 ±  ops/s
CharsToString.stringJoin             JAVA7     100     180763.740 ±  ops/s
CharsToString.stringJoin             JAVA7     200      86729.675 ±  ops/s
CharsToString.stringJoin             JAVA7     500      38560.347 ±  ops/s
CharsToString.stringJoin             JAVA7    1000      17798.159 ±  ops/s

As you can see, the last version (iterableForEach) is actually the fastest one, with the Java 7 and Guava versions at least in a similar ballpark. For Sizes under several hundred elements, Streams fail miserably, they are obviously optimized for large data sets. But at 1000 elements, they perform significantly better and almost on par with the Java 7 version. At about 10000 elements (not on this chart), Streams outperform the other solutions.

The benchmark code is available as a GitHub gist, feel free to tinker with the parameters and check the results on your machine.




回答2:


Given x is a Iterable<Character> you can convert in a String with:

public static String iterableToString(Iterable<Character> chars){
   return Stream.of(x).map(String::valueOf).collect(Collectors.joining());
}



回答3:


You can use StreamSupport class:

get the Iterable:

Iterable<Character> iterableChars = Arrays.asList('1', '2', '3', '4');

append to string:

String commaSeparatedChars = StreamSupport.stream(iterableChars.spliterator(), false)
            .map(i -> i.toString()).collect(Collectors.joining(", "));

and print it:

System.out.println(commaSeparatedChars );



回答4:


Simple solution using StringBuilder:

Iterable<Character> cs = ...; // wherever you get this from

StringBuilder sb = new StringBuilder();
for (Character c : cs) {
    sb.append(c);
}
String result = sb.toString();

Solution using streams:

String result = cs.stream()
         .collect(StringBuilder::new, StringBuilder::append, StringBuilder::append)
         .toString();


来源:https://stackoverflow.com/questions/42627108/best-way-to-convert-iterablecharacter-to-string

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!