我怎样才能收集一个Java 8stream到一个番石榴ImmutableCollection?
我想要做以下事情:
List<Integer> list = IntStream.range(0, 7).collect(Collectors.toList());  但是结果列表是番石榴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)
 这是collectAndThen collectingAndThen器有用的地方: 
 List<Integer> list = IntStream.range(0, 7).boxed() .collect(collectingAndThen(toList(), ImmutableList::copyOf)); 
 它将转换应用于刚刚创build的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(); 
如果这个选项对你来说有点冗长,并且你想在很多地方使用它,你可以创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的静态工具方法中定义。 这比创build自己的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()); 
  Alexis公认的答案中的toImmutableList()方法现在包含在Guava 21中 ,可以用作: 
 ImmutableList<Integer> list = IntStream.range(0, 7).boxed().collect(ImmutableList.toImmutableList()); 
虽然不是直接回答我的问题(它不使用收集器),但这是一个相当优雅的方法,不使用中间集合:
 Stream<Integer> stream = IntStream.range(0, 7).boxed(); List<Integer> list = ImmutableList.copyOf(stream.iterator()); 
来源 。
仅供参考,在没有Java 8的Guava中有一个合理的方法:
 ImmutableSortedSet<Integer> set = ContiguousSet.create( Range.closedOpen(0, 7), DiscreteDomain.integers()); ImmutableList<Integer> list = set.asList(); 
 如果你实际上不需要List语义,并且可以使用NavigableSet ,那甚至更好,因为ContiguousSet不必实际存储所有元素(只是Range和DiscreteDomain )。