你如何创建一个收集到com.google.common.collect.ImmutableSet的java.util.stream.Collector?

时间:2014-12-22 23:45:19

标签: java java-8 guava collectors

这对我来说似乎太棘手了,因为ImmutableSet个实例仅使用ImmutableSet.Builder个实例构建,这些实例没有实现Collection因此您不能只使用Collectors.toCollection(ImmutableSet::new)Collectors.toCollection(ImmutableSet.Builder::new)

6 个答案:

答案 0 :(得分:6)

现在已经内置了番石榴,

ImmutableSet#toImmutableSet

使用like,

something.stream().collect(ImmutableSet.toImmutableSet())

答案 1 :(得分:4)

事实上,3个月后:-),而不是为此定义一个完整的类,您可以使用Collector.of并将其包装在一个简单的实用程序方法中:

public static <T> Collector<T, Builder<T>, ImmutableSet<T>> immutableSetCollector() {
    return Collector.of(Builder<T>::new, Builder<T>::add, (s, r) -> s.addAll(r.build()), Builder<T>::build);
}

然后:

import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSet.Builder;
....

ImmutableSet<Point2D> set = 
    Stream.of(new Point2D(1, 2), ...).collect(immutableSetCollector());

答案 2 :(得分:2)

我们可以通过扩展Collector接口来编写自定义收集器。

这是一个可靠的参考资料,可以说明它的细节:http://java.dzone.com/articles/introduction-writing-custom

答案 3 :(得分:1)

这是我找到的最接近的地方:

Set<String> set = list.stream().collect(ImmutableSet.Builder<String>::new, ImmutableSet.Builder<String>::add, (builder1, builder2) -> builder1.addAll(builder2.build())).build();

没有方法可以将一个构建器的元素附加到另一个构建器,只有Iterable或Iterator,因此您不能使用方法引用。

答案 4 :(得分:1)

因此,在这种情况下编写自定义收集器似乎并不像我想象的那样困难:

package org.tendiwa.collections;

import com.google.common.collect.ImmutableSet;

import java.util.Set;
import java.util.function.BiConsumer;
import java.util.function.BinaryOperator;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Collector;

public class ImmutableSetCollector<T> implements Collector<T, ImmutableSet.Builder<T>, ImmutableSet<T>> {

    @Override
    public Supplier<ImmutableSet.Builder<T>> supplier() {
        return ImmutableSet.Builder::new;
    }

    @Override
    public BiConsumer<ImmutableSet.Builder<T>, T> accumulator() {
        return (builder, element) -> builder.add(element);
    }

    @Override
    public BinaryOperator<ImmutableSet.Builder<T>> combiner() {
        return (b1, b2) -> b1.addAll(b2.build());
    }

    @Override
    public Function<ImmutableSet.Builder<T>, ImmutableSet<T>> finisher() {
        return ImmutableSet.Builder::build;
    }

    @Override
    public Set<Characteristics> characteristics() {
        return ImmutableSet.of();
    }
}

用法:

public static void main(String[] args) {
    ImmutableSet<Point2D> set = Arrays.asList(
        new Point2D(1, 2),
        new Point2D(2, 4),
        new Point2D(3, 5),
        new Point2D(4, 4),
        new Point2D(5, 6),
        new Point2D(8, 6)
    ).stream().collect(new ImmutableSetCollector<>());
    System.out.println(set);
}

输出:

[{1.0:2.0}, {2.0:4.0}, {3.0:5.0}, {4.0:4.0}, {5.0:6.0}, {8.0:6.0}]

答案 5 :(得分:1)

此功能在guava-jdk8库(我创作的)中已经开箱即用。