update descargar actualizar java-8 guava java-stream

java-8 - descargar - java 8 update 171



¿Cómo puedo recopilar una secuencia de Java 8 en una colección immutable de guayaba? (5)

Me gustaría hacer lo siguiente:

List<Integer> list = IntStream.range(0, 7).collect(Collectors.toList());

pero de alguna manera la lista resultante es una implementación de la Lista ImmutableList de Guava.

Se que podria 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)


Aquí es donde el collectingAndThen collectAndThen es útil:

List<Integer> list = IntStream.range(0, 7).boxed() .collect(collectingAndThen(toList(), ImmutableList::copyOf));

Aplica la transformación a la List que acaba de construir; resultando en una ImmutableList .

O puede recopilar directamente en el Builder y llamar a build() 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<>());

Por si acaso el enlace desaparece 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 simple que crear tu propia clase de Collector .

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());


El método toImmutableList() en la respuesta aceptada de Alexis ahora se incluye en Guava 21 y se puede usar como:

ImmutableList<Integer> list = IntStream.range(0, 7) .boxed() .collect(ImmutableList.toImmutableList());


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 realmente no necesita la semántica de la List y solo puede usar un NavigableSet , eso es aún mejor ya que un ContiguousSet no tiene que almacenar todos los elementos (solo el Range y el DiscreteDomain ).


Por cierto: desde JDK 10 se puede hacer en Java puro:

List<Integer> list = IntStream.range(0, 7) .collect(Collectors.toUnmodifiableList());

También disponible toUnmodifiableSet y toUnmodifiableMap .

El recopilador interno se realizó a través de List.of(list.toArray())


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());

Source