如何制作收集到com.google.common.collect.ImmutableSet的java.util.stream.Collector?

如何制作收集到com.google.common.collect.ImmutableSet的java.util.stream.Collector?,java,java-8,guava,collectors,Java,Java 8,Guava,Collectors,这对我来说似乎太棘手了,因为ImmutableSet实例只使用ImmutableSet.Builder实例构建,而这些实例不实现Collection,所以不能只使用collector.toCollection(ImmutableSet::new)或collector.toCollection(ImmutableSet.Builder::new)这是我找到的最接近的: Set<String> set = list.stream().collect(ImmutableSet.Builde

这对我来说似乎太棘手了,因为
ImmutableSet
实例只使用
ImmutableSet.Builder
实例构建,而这些实例不实现
Collection
,所以不能只使用
collector.toCollection(ImmutableSet::new)
collector.toCollection(ImmutableSet.Builder::new)

这是我找到的最接近的:

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

没有方法可以将一个生成器的元素附加到另一个生成器中,只有一个Iterable或迭代器,因此您不能对此生成器使用方法引用。

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


这里有一个可靠的参考资料详细介绍了它:

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

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();
    }
}
事实上,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);
}
公共静态收集器immutableSetCollector(){
返回Collector.of(Builder::new,Builder::add,(s,r)->s.addAll(r.build()),Builder::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());
import com.google.common.collect.ImmutableSet;
导入com.google.common.collect.ImmutableSet.Builder;
....
不可变表集=
Stream.of(新的Point2D(1,2),…).collect(immutableSetCollector());

此功能在库(我自己编写)中开箱即用。

此功能现在内置于番石榴中

使用like

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

我粘贴的链接的代码引用或多或少与您的代码引用相同。@KuriosCoder,除了在
charactersitics()
中指出,当
ImmutableSet
实际具有用户根据其文档指定的顺序时,生成的集合是无序的:有趣。默认情况下,是否设置为无序@kuriouscoder集合排序没有约束,因此由实现决定。特点。无德雷德只是意味着我们不能依赖订购的电视机。好文章,这几乎正是我所想到的。半规范的JDK 8 fork of Guava的实现更为简单:@LouisWasserman直接使用而不是
收集然后
收集
?构建器不应该像那个例子那样被合并;这并不明显是可取的。请遵守完整的披露指南。注意到@Drew,我不知道这是个问题,但我肯定会相应地更新答案。我们中的一些人每天复习1000分左右。。。你的代表性很高。问题在于代表性
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSet.Builder;
....

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