Jak mogę zebrać strumień Java 8 do Guava ImmutableCollection?
Chciałbym wykonać następujące czynności:
List<Integer> list = IntStream.range(0, 7).collect(Collectors.toList());
Ale w taki sposób, że wynikowa lista jest implementacją ImmutableList
.
I know I could do
List<Integer> list = IntStream.range(0, 7).collect(Collectors.toList());
List<Integer> immutableList = ImmutableList.copyOf(list);
/ Align = "left" / Próbowałem
List<Integer> list = IntStream.range(0, 7)
.collect(Collectors.toCollection(ImmutableList::of));
Ale wyrzuciło wyjątek:
Java.lang.UnsupportedOperationException na kom.google.pospolite.zbieraj.ImmutableCollection.add (ImmutableCollection.java: 96)
5 answers
Tutaj przydaje się kolektor collectingAndThen
:
List<Integer> list = IntStream.range(0, 7).boxed()
.collect(collectingAndThen(toList(), ImmutableList::copyOf));
Stosuje transformację do List
, które właśnie zbudowałeś; w rezultacie otrzymujesz ImmutableList
.
Lub możesz odebrać bezpośrednio w Builder
i zadzwonić build()
na końcu:
List<Integer> list = IntStream.range(0, 7)
.collect(Builder<Integer>::new, Builder<Integer>::add, (builder1, builder2) -> builder1.addAll(builder2.build()))
.build();
Jeśli ta opcja jest dla ciebie trochę słowna i chcesz jej używać w wielu miejscach, możesz utworzyć własny kolektor:
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();
}
}
A potem:
List<Integer> list = IntStream.range(0, 7)
.boxed()
.collect(new ImmutableListCollector<>());
Na wszelki wypadek link zniknie w komentarzach; mój drugi podejście może być zdefiniowane w statycznej metodzie użytkowej, która po prostu używa Collector.of
. To prostsze niż tworzenie własnej klasy 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);
}
I użycie:
List<Integer> list = IntStream.range(0, 7)
.boxed()
.collect(toImmutableList());
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-03-12 16:21:56
Metoda toImmutableList()
w zaakceptowanej odpowiedzi Alexisa jest teraz włączona do Guava 21 i może być używana jako:
ImmutableList<Integer> list = IntStream.range(0, 7)
.boxed()
.collect(ImmutableList.toImmutableList());
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-06-15 00:18:03
Chociaż nie jest to bezpośrednia odpowiedź na moje pytanie( nie używa kolekcjonerów), jest to dość eleganckie podejście, które nie wykorzystuje zbiorów pośrednich:
Stream<Integer> stream = IntStream.range(0, 7).boxed();
List<Integer> list = ImmutableList.copyOf(stream.iterator());
Źródło .
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-07-15 12:38:16
Dla twojej wiadomości, jest rozsądny sposób, aby to zrobić w Guava bez Java 8:
ImmutableSortedSet<Integer> set = ContiguousSet.create(
Range.closedOpen(0, 7), DiscreteDomain.integers());
ImmutableList<Integer> list = set.asList();
Jeśli nie potrzebujesz semantyki List
i możesz po prostu użyć NavigableSet
, to nawet lepiej, ponieważ ContiguousSet
nie musi przechowywać wszystkich elementów w nim (tylko Range
i DiscreteDomain
).
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-03-12 18:15:17
BTW: od JDK 10 można to zrobić w czystej Javie:
List<Integer> list = IntStream.range(0, 7)
.collect(Collectors.toUnmodifiableList());
Również toUnmodifiableSet
i toUnmodifiableMap
dostępne.
Wewnątrz kolektora wykonano przez List.of(list.toArray())
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-09-24 02:11:25