gil.fernandes
gil.fernandes

Reputation: 14621

How to convert a range to a delimited string in Java 8+

How can you convert a range in Java (either using java.util.stream.LongStream or java.util.stream.IntStream) to a delimited string in Java?

I have tried:

String str = LongStream.range(16, 30)
                .boxed()
                .map(String::valueOf)
                .collect(Collectors.joining(","));
System.out.println(str);

This prints:

16,17,18,19,20,21,22,23,24,25,26,27,28,29

The same can be used with IntStream. Is there a more convenient conversion of a range to a delimited string?

Upvotes: 10

Views: 2946

Answers (3)

Eugene
Eugene

Reputation: 120978

Seriously, just for the fun of it. Using guava:

String result = ContiguousSet.create(
                       Range.closedOpen(16, 31), DiscreteDomain.integers())
                             .asList()
                             .toString();

Or

 String result = String.join(",",
            IntStream.rangeClosed(16, 30).mapToObj(String::valueOf).toArray(String[]::new));

Or:

String result = String.join(",",
            () -> IntStream.rangeClosed(16, 31).mapToObj(x -> (CharSequence) String.valueOf(x)).iterator());

Or (seems like I got carried away a bit with this):

String result = IntStream.rangeClosed(16, 31)
            .boxed()
            .collect(
                    Collector.of(
                            () -> new Object() {
                                StringBuilder sb = new StringBuilder();
                            },
                            (obj, i) -> obj.sb.append(i).append(",")
                            ,
                            (left, right) -> {
                                left.sb.append(right.sb.toString());
                                return left;
                            },
                            x -> {
                                x.sb.setLength(x.sb.length() - 1);
                                return x.sb.toString();
                            })
            );

And after Holger's good points, here is even a simpler version:

    StringBuilder sb = IntStream.range(16, 30)
            .collect(
                    StringBuilder::new,
                    (builder, i) -> builder.append(i).append(", "),
                    StringBuilder::append);

    if (sb.length() != 0) {
        sb.setLength(sb.length() - 2);
    }
    String result = sb.toString(); 

Upvotes: 8

Oleksandr Pyrohov
Oleksandr Pyrohov

Reputation: 16266

With IntStream.mapToObj:

String s = IntStream.range(16, 30)
                    .mapToObj(String::valueOf)
                    .collect(Collectors.joining(","));

Upvotes: 7

mark42inbound
mark42inbound

Reputation: 374

If your sense of convenience implies less code, there is no need to explicitly map the Long to String. They can be simply mapped while collecting process. Here's the code to do so:

List<String> str = LongStream.range(16, 30)
            .boxed()
            .collect(Collectors.mapping(l -> String.valueOf(l), Collectors.toList()));
System.out.println(str.toString());

The result is:

[16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29]

In response to the comment to whether boxing should be avoided, it has to happen anyway. The range() in this case returns an object of LongStream which has to be converted to a stream of Long.

According to @Jubobs The mapToObject() effectively returns stream of Long from the LongStream object.

Upvotes: 0

Related Questions