I would like to do the following:
我想做以下工作:
List<Integer> list = IntStream.range(0, 7).collect(Collectors.toList());
but in a way that the resulting list is an implementation of Guava's ImmutableList
.
但在某种程度上,结果列表是Guava的ImmutableList的实现。
I know I could do
我知道我能做到。
List<Integer> list = IntStream.range(0, 7).collect(Collectors.toList());
List<Integer> immutableList = ImmutableList.copyOf(list);
but I would like to collect to it directly. I've tried
但是我想直接收集。我试过了
List<Integer> list = IntStream.range(0, 7)
.collect(Collectors.toCollection(ImmutableList::of));
but it threw an exception:
但它却引发了一个例外:
java.lang.UnsupportedOperationException at com.google.common.collect.ImmutableCollection.add(ImmutableCollection.java:96)
. lang。UnsupportedOperationException在com.google.common.collect.ImmutableCollection.add方式(ImmutableCollection.java:96)
4 个解决方案
#1
52
This is where the collectingAndThen
collector is useful:
这是收集和收集的有用的地方:
List<Integer> list = IntStream.range(0, 7).boxed()
.collect(collectingAndThen(toList(), ImmutableList::copyOf));
It applies the transformation to the List
you just built; resulting in an ImmutableList
.
它将转换应用到刚刚构建的列表;导致一个ImmutableList。
Or you could directly collect into the Builder
and call build()
at the end:
或者您可以直接将其收集到构建器中,并在最后调用build():
List<Integer> list = IntStream.range(0, 7)
.collect(Builder<Integer>::new, Builder<Integer>::add, (builder1, builder2) -> builder1.addAll(builder2.build()))
.build();
If this option is a bit-verbose to you and you want to use it in many places, you can create your own collector:
如果这个选项对您来说是位冗长的,并且您想在许多地方使用它,您可以创建自己的收集器:
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();
}
}
and then:
然后:
List<Integer> list = IntStream.range(0, 7)
.boxed()
.collect(new ImmutableListCollector<>());
Just in case the link disappears in the comments; my second approach could be defined in a static utility method that simply uses Collector.of
. It's simpler than creating your own Collector
class.
以防链接在评论中消失;我的第二种方法可以在一个简单使用Collector.of的静态实用工具方法中定义。它比创建自己的收集器类简单。
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);
}
and the usage:
和用法:
List<Integer> list = IntStream.range(0, 7)
.boxed()
.collect(toImmutableList());
#2
52
The toImmutableList()
method in the accepted answer of Alexis is now included in Guava 21 and can be used as:
在被接受的亚历克西斯的回答中,toImmutableList()方法现在已经包含在Guava 21中,可以用作:
ImmutableList<Integer> list = IntStream.range(0, 7).boxed().collect(ImmutableList.toImmutableList());
#3
13
While not a direct answer to my question (it does not use collectors), this is a fairly elegant approach which doesn't use intermediate collections:
虽然这不是我的问题的直接答案(它不使用收集器),但这是一个相当优雅的方法,它不使用中间集合:
Stream<Integer> stream = IntStream.range(0, 7).boxed();
List<Integer> list = ImmutableList.copyOf(stream.iterator());
源。
#4
3
FYI, there's a reasonable way to do this in Guava without Java 8:
FYI,在没有Java 8的番石榴中有一种合理的方法:
ImmutableSortedSet<Integer> set = ContiguousSet.create(
Range.closedOpen(0, 7), DiscreteDomain.integers());
ImmutableList<Integer> list = set.asList();
If you don't actually need the List
semantics and can just use a NavigableSet
, that's even better since a ContiguousSet
doesn't have to actually store all the elements in it (just the Range
and DiscreteDomain
).
如果您实际上不需要列表语义,并且只需要使用NavigableSet,那就更好了,因为一个连续的集合不需要实际存储所有的元素(只是范围和离散域)。
#1
52
This is where the collectingAndThen
collector is useful:
这是收集和收集的有用的地方:
List<Integer> list = IntStream.range(0, 7).boxed()
.collect(collectingAndThen(toList(), ImmutableList::copyOf));
It applies the transformation to the List
you just built; resulting in an ImmutableList
.
它将转换应用到刚刚构建的列表;导致一个ImmutableList。
Or you could directly collect into the Builder
and call build()
at the end:
或者您可以直接将其收集到构建器中,并在最后调用build():
List<Integer> list = IntStream.range(0, 7)
.collect(Builder<Integer>::new, Builder<Integer>::add, (builder1, builder2) -> builder1.addAll(builder2.build()))
.build();
If this option is a bit-verbose to you and you want to use it in many places, you can create your own collector:
如果这个选项对您来说是位冗长的,并且您想在许多地方使用它,您可以创建自己的收集器:
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();
}
}
and then:
然后:
List<Integer> list = IntStream.range(0, 7)
.boxed()
.collect(new ImmutableListCollector<>());
Just in case the link disappears in the comments; my second approach could be defined in a static utility method that simply uses Collector.of
. It's simpler than creating your own Collector
class.
以防链接在评论中消失;我的第二种方法可以在一个简单使用Collector.of的静态实用工具方法中定义。它比创建自己的收集器类简单。
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);
}
and the usage:
和用法:
List<Integer> list = IntStream.range(0, 7)
.boxed()
.collect(toImmutableList());
#2
52
The toImmutableList()
method in the accepted answer of Alexis is now included in Guava 21 and can be used as:
在被接受的亚历克西斯的回答中,toImmutableList()方法现在已经包含在Guava 21中,可以用作:
ImmutableList<Integer> list = IntStream.range(0, 7).boxed().collect(ImmutableList.toImmutableList());
#3
13
While not a direct answer to my question (it does not use collectors), this is a fairly elegant approach which doesn't use intermediate collections:
虽然这不是我的问题的直接答案(它不使用收集器),但这是一个相当优雅的方法,它不使用中间集合:
Stream<Integer> stream = IntStream.range(0, 7).boxed();
List<Integer> list = ImmutableList.copyOf(stream.iterator());
源。
#4
3
FYI, there's a reasonable way to do this in Guava without Java 8:
FYI,在没有Java 8的番石榴中有一种合理的方法:
ImmutableSortedSet<Integer> set = ContiguousSet.create(
Range.closedOpen(0, 7), DiscreteDomain.integers());
ImmutableList<Integer> list = set.asList();
If you don't actually need the List
semantics and can just use a NavigableSet
, that's even better since a ContiguousSet
doesn't have to actually store all the elements in it (just the Range
and DiscreteDomain
).
如果您实际上不需要列表语义,并且只需要使用NavigableSet,那就更好了,因为一个连续的集合不需要实际存储所有的元素(只是范围和离散域)。