Czy istnieje Kolekcjoner, który zbiera do zestawu zachowującego zamówienia?

107

Collectors.toSet()nie zachowuje porządku. Mógłbym zamiast tego użyć List, ale chcę wskazać, że wynikowa kolekcja nie pozwala na powielanie elementów, a dokładnie do tego Setsłuży interfejs.

gvlasov
źródło
Myślę, że coś takiego nie istnieje. Wiem, że też go potrzebowałem i musiałem napisać własny.
markspace
Czy SortedSetzadziała? Jeśli nie, wybór należy do niestandardowych.
AntonH
@AntonH Nie, wolałbym operacje O (1) zamiast O (log n).
gvlasov
1
Opublikowałem ten kod, nie jest to dokładnie to, czego potrzebujesz, ale może ci zacząć.
markspace

Odpowiedzi:

203

Możesz użyć toCollectioni podać konkretną instancję zestawu, który chcesz. Na przykład, jeśli chcesz zachować zamówienie reklamowe:

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

Na przykład:

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.
źródło
Fajnie, dokładnie tego potrzebuję, ale myślę, ImmutableSetże w moim przypadku guawa byłaby jeszcze lepsza. Jakieś pomysły, jak mogę zrobić kolekcjonera, który zbiera ImmutableSet? Jego instancje są zbudowane z rozszerzeniem, ImmutableSet.Builderktóre nie jest a Collection, więc nie mogę dowiedzieć się, jak w takim przypadku utworzyłbyś Supplierfor Collectors.toCollection().
gvlasov
@Susei Spróbuję się temu przyjrzeć. Alternatywą byłoby zwrócenie niemodyfikowalnego zestawu. Np .:Set<String> linkedSet = list.stream().collect(Collectors.toCollection(LinkedHashSet::new)); linkedSet = Collections.unmodifiableSet(linkedSet);
Alexis C.
@Susei Najbliższe, które znalazłem: Set<String> set = list.stream().collect( ImmutableSet.Builder<String>::new, ImmutableSet.Builder<String>::add, (builder1, builder2) -> builder1.addAll(builder2.build())).build();Nie jestem pewien, czy jest to lepsze podejście, zawijając wynikowy zestaw Collections.unmodifiableSet.
Alexis C.
Oto dedykowane pytanie, ponieważ jest już poza tematem (i oczywiście dla większej liczby przedstawicieli za świetne odpowiedzi): stackoverflow.com/questions/27612165/ ...
gvlasov