Existe um Coletor que coleta para um Conjunto que preserva a ordem?

107

Collectors.toSet()não preserva a ordem. Eu poderia usar Lists em vez disso, mas quero indicar que a coleção resultante não permite a duplicação de elementos, que é exatamente para que Setserve a interface.

gvlasov
fonte
Eu não acho que tal coisa exista. Sei que também precisava de um e tive que escrever o meu próprio.
markspace
Funcionaria SortedSet? Caso contrário, o costume é o caminho a percorrer.
AntonH
@AntonH Não, eu preferiria operações O (1) a O (log n).
gvlasov
1
Publiquei esse código, não é exatamente o que você precisa, mas pode ajudá-lo a começar.
markspace

Respostas:

203

Você pode usar toCollectione fornecer a instância concreta do conjunto que deseja. Por exemplo, se você deseja manter o pedido de inserção:

Set<MyClass> set = myStream.collect(Collectors.toCollection(LinkedHashSet::new));

Por exemplo:

public class Test {    
    public static final void main(String[] args) {
        List<String> list = Arrays.asList("b", "c", "a");

        Set<String> linkedSet = 
            list.stream().collect(Collectors.toCollection(LinkedHashSet::new));

        Set<String> collectorToSet = 
            list.stream().collect(Collectors.toSet());

        System.out.println(linkedSet); //[b, c, a]
        System.out.println(collectorToSet); //[a, b, c]
    }
}
Alexis C.
fonte
Legal, é exatamente disso que preciso, mas acho que Goiaba ImmutableSetseria ainda melhor no meu caso. Alguma ideia de como posso fazer um colecionador que colecione ImmutableSet? Suas instâncias são construídas com um ImmutableSet.Builderque não é um Collection, portanto, não consigo descobrir como você faria um Supplierfor Collectors.toCollection()nesse caso.
gvlasov
@Susei vou tentar dar uma olhada nisso. Uma alternativa seria retornar um conjunto não modificável. Ex:Set<String> linkedSet = list.stream().collect(Collectors.toCollection(LinkedHashSet::new)); linkedSet = Collections.unmodifiableSet(linkedSet);
Alexis C.
@Susei O mais próximo que encontrei: Set<String> set = list.stream().collect( ImmutableSet.Builder<String>::new, ImmutableSet.Builder<String>::add, (builder1, builder2) -> builder1.addAll(builder2.build())).build();Não tenho certeza se é uma abordagem melhor envolvendo o conjunto resultante com Collections.unmodifiableSet.
Alexis C.
Aqui está uma pergunta específica, uma vez que já está fora do assunto (e para mais representantes para ótimas respostas, é claro): stackoverflow.com/questions/27612165/…
gvlasov