Я бы хотел сделать следующее:
List<Integer> list = IntStream.range(0, 7).collect(Collectors.toList());
но в том смысле, что полученный список является реализацией Guava ImmutableList
.
Я знаю, что могу сделать
List<Integer> list = IntStream.range(0, 7).collect(Collectors.toList());
List<Integer> immutableList = ImmutableList.copyOf(list);
но я хотел бы собирать к нему напрямую. я пытался
List<Integer> list = IntStream.range(0, 7)
.collect(Collectors.toCollection(ImmutableList::of));
но это вызвало исключение:
java.lang.UnsupportedOperationException в com.google.common.collect.ImmutableCollection.add (ImmutableCollection.java:96)
java-8
guava
java-stream
Золтан
источник
источник
@Beta
с Guava 26.0.Вот
collectingAndThen
тут и пригодится сборщик:List<Integer> list = IntStream.range(0, 7).boxed() .collect(collectingAndThen(toList(), ImmutableList::copyOf));
Он применяет преобразование к
List
только что построенному; в результате получается файлImmutableList
.Или вы можете напрямую собрать в
Builder
и позвонитьbuild()
в конце:List<Integer> list = IntStream.range(0, 7) .collect(Builder<Integer>::new, Builder<Integer>::add, (builder1, builder2) -> builder1.addAll(builder2.build())) .build();
Если эта опция кажется вам многословной и вы хотите использовать ее во многих местах, вы можете создать свой собственный сборщик:
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(); } }
а потом:
List<Integer> list = IntStream.range(0, 7) .boxed() .collect(new ImmutableListCollector<>());
На всякий случай ссылка в комментариях пропадает; мой второй подход может быть определен в статическом служебном методе, который просто использует
Collector.of
. Это проще, чем создавать свой собственный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); }
и использование:
List<Integer> list = IntStream.range(0, 7) .boxed() .collect(toImmutableList());
источник
ImmutableList.Builder
быть какая-нибудь помощь?build()
.Collector
класс :-)ImmutableList<Integer>
(вместоList<Integer>
).Хотя это не прямой ответ на мой вопрос (он не использует сборщики), это довольно элегантный подход, который не использует промежуточные коллекции:
Stream<Integer> stream = IntStream.range(0, 7).boxed(); List<Integer> list = ImmutableList.copyOf(stream.iterator());
Источник .
источник
Кстати: начиная с JDK 10 это можно сделать на чистой Java:
List<Integer> list = IntStream.range(0, 7) .collect(Collectors.toUnmodifiableList());
Также
toUnmodifiableSet
и вtoUnmodifiableMap
наличии.Внутри коллектора это было сделано через
List.of(list.toArray())
источник
ImmutableCollections.List12
andImmutableCollections.ListN
! = Guava'sImmutableList
. С практической точки зрения вы в основном правы, но все же имеет смысл упомянуть этот нюанс в своем ответе.К вашему сведению, есть разумный способ сделать это в Guava без Java 8:
ImmutableSortedSet<Integer> set = ContiguousSet.create( Range.closedOpen(0, 7), DiscreteDomain.integers()); ImmutableList<Integer> list = set.asList();
Если вам на самом деле не нужна
List
семантика и вы можете просто использовать aNavigableSet
, это даже лучше, поскольку aContiguousSet
не обязательно хранить все элементы в нем (толькоRange
иDiscreteDomain
).источник