Me gustaría hacer lo siguiente:
List<Integer> list = IntStream.range(0, 7).collect(Collectors.toList());
pero de una manera que la lista resultante es una implementación de la de Guava ImmutableList.
Sé que podría hacer
List<Integer> list = IntStream.range(0, 7).collect(Collectors.toList());
List<Integer> immutableList = ImmutableList.copyOf(list);
pero me gustaría cobrarle directamente. He intentado
List<Integer> list = IntStream.range(0, 7)
.collect(Collectors.toCollection(ImmutableList::of));
pero arrojó una excepción:
java.lang.UnsupportedOperationException en com.google.common.collect.ImmutableCollection.add (ImmutableCollection.java:96)
java-8
guava
java-stream
Zoltán
fuente
fuente

@Betapartir de Guayaba 26.0.Aquí es donde el
collectingAndThencolector es útil:List<Integer> list = IntStream.range(0, 7).boxed() .collect(collectingAndThen(toList(), ImmutableList::copyOf));Aplica la transformación a la
Listque acaba de construir; resultando en unImmutableList.O puede cobrar directamente en el
Buildery llamarbuild()al final:List<Integer> list = IntStream.range(0, 7) .collect(Builder<Integer>::new, Builder<Integer>::add, (builder1, builder2) -> builder1.addAll(builder2.build())) .build();Si esta opción es un poco detallada para usted y desea usarla en muchos lugares, puede crear su propio recopilador:
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(); } }y entonces:
List<Integer> list = IntStream.range(0, 7) .boxed() .collect(new ImmutableListCollector<>());En caso de que el enlace desaparezca en los comentarios; mi segundo enfoque podría definirse en un método de utilidad estática que simplemente usa
Collector.of. Es más sencillo que crear tu propiaCollectorclase.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); }y el uso:
List<Integer> list = IntStream.range(0, 7) .boxed() .collect(toImmutableList());fuente
ImmutableList.Builderser de alguna ayuda?build().Collectorclase :-)ImmutableList<Integer>(en lugar deList<Integer>).Si bien no es una respuesta directa a mi pregunta (no usa colectores), este es un enfoque bastante elegante que no usa colecciones intermedias:
Stream<Integer> stream = IntStream.range(0, 7).boxed(); List<Integer> list = ImmutableList.copyOf(stream.iterator());Fuente .
fuente
Por cierto: desde JDK 10 se puede hacer en Java puro:
List<Integer> list = IntStream.range(0, 7) .collect(Collectors.toUnmodifiableList());También
toUnmodifiableSetytoUnmodifiableMapdisponible.Dentro del colector se hizo a través de
List.of(list.toArray())fuente
ImmutableCollections.List12yImmutableCollections.ListN! = GuayabaImmutableList. Desde una perspectiva práctica, en su mayoría tiene razón, pero aún tendría sentido mencionar este matiz en su respuesta.Para su información, hay una forma razonable de hacer esto en Guava sin Java 8:
ImmutableSortedSet<Integer> set = ContiguousSet.create( Range.closedOpen(0, 7), DiscreteDomain.integers()); ImmutableList<Integer> list = set.asList();Si en realidad no necesita la
Listsemántica y solo puede usar aNavigableSet, eso es aún mejor, yaContiguousSetque a no tiene que almacenar todos los elementos en él (solo elRangeyDiscreteDomain).fuente