I would like to do the following:
List list = IntStream.range(0, 7).collect(Collectors.toList());
but in a way that the resu
BTW: since JDK 10 it can be done in pure Java:
List<Integer> list = IntStream.range(0, 7)
.collect(Collectors.toUnmodifiableList());
Also toUnmodifiableSet
and toUnmodifiableMap
available.
Inside collector it was done via List.of(list.toArray())
This is where the collectingAndThen
collector is useful:
List<Integer> list = IntStream.range(0, 7).boxed()
.collect(collectingAndThen(toList(), ImmutableList::copyOf));
It applies the transformation to the List
you just built; resulting in an ImmutableList
.
Or you could directly collect into the Builder
and call build()
at the end:
List<Integer> list = IntStream.range(0, 7)
.collect(Builder<Integer>::new, Builder<Integer>::add, (builder1, builder2) -> builder1.addAll(builder2.build()))
.build();
If this option is a bit-verbose to you and you want to use it in many places, you can create your own collector:
class ImmutableListCollector<T> implements Collector<T, Builder<T>, ImmutableList<T>> {
@Override
public Supplier<Builder<T>> supplier() {
return Builder::new;
}
@Override
public BiConsumer<Builder<T>, T> accumulator() {
return (b, e) -> b.add(e);
}
@Override
public BinaryOperator<Builder<T>> combiner() {
return (b1, b2) -> b1.addAll(b2.build());
}
@Override
public Function<Builder<T>, ImmutableList<T>> finisher() {
return Builder::build;
}
@Override
public Set<Characteristics> characteristics() {
return ImmutableSet.of();
}
}
and then:
List<Integer> list = IntStream.range(0, 7)
.boxed()
.collect(new ImmutableListCollector<>());
Just in case the link disappears in the comments; my second approach could be defined in a static utility method that simply uses Collector.of
. It's simpler than creating your own Collector
class.
public static <T> Collector<T, Builder<T>, ImmutableList<T>> toImmutableList() {
return Collector.of(Builder<T>::new, Builder<T>::add, (l, r) -> l.addAll(r.build()), Builder<T>::build);
}
and the usage:
List<Integer> list = IntStream.range(0, 7)
.boxed()
.collect(toImmutableList());
FYI, there's a reasonable way to do this in Guava without Java 8:
ImmutableSortedSet<Integer> set = ContiguousSet.create(
Range.closedOpen(0, 7), DiscreteDomain.integers());
ImmutableList<Integer> list = set.asList();
If you don't actually need the List
semantics and can just use a NavigableSet
, that's even better since a ContiguousSet
doesn't have to actually store all the elements in it (just the Range
and DiscreteDomain
).
The toImmutableList()
method in the accepted answer of Alexis is now included in Guava 21 and can be used as:
ImmutableList<Integer> list = IntStream.range(0, 7)
.boxed()
.collect(ImmutableList.toImmutableList());
Edit: Removed @Beta
from ImmutableList.toImmutableList
along with other frequently used APIs in Release 27.1 (6242bdd).
While not a direct answer to my question (it does not use collectors), this is a fairly elegant approach which doesn't use intermediate collections:
Stream<Integer> stream = IntStream.range(0, 7).boxed();
List<Integer> list = ImmutableList.copyOf(stream.iterator());
Source.