簡體   English   中英

如何使用java8流對TreeSet的列表進行排序

[英]How do I sort a List of TreeSets with java8 streams

我的列表包含[1,3,5][2,6,4]等集合,大小相同。 我試過這樣做,但似乎沒有用。

List<TreeSet<T>> block;
    for(TreeSet<T> t : block){
        block.stream().sorted((n,m)->n.compareTo(m)).collect(Collectors.toSet());

    }

我想要的最終結果是[1,2,3][4,5,6]

我可以嘗試在ArrayList添加所有元素並對其進行排序,然后創建一個新的TreeSet List 但是有一種襯墊嗎?

更新:

List<T> list=new ArrayList<T>();
    for(TreeSet<T> t : block){

        for(T t1 : t)
        {
            list.add(t1);   

        }
    }

    list=list.stream().sorted((n,m)->n.compareTo(m)).collect(Collectors.toList());

這有效但可以簡化嗎?

@ Eugene的答案很甜蜜,因為番石榴很甜。 但是,如果您的類路徑中沒有Guava,這是另一種方式:

List<Set<Integer>> list = block.stream()
    .flatMap(Set::stream)
    .sorted()
    .collect(partitioning(3));

首先,我將所有集合平面化為一個流,然后我將所有元素排序,最后,我將整個排序流收集到集合列表中。 為此,我正在調用一個使用自定義收集器的輔助方法:

private static <T> Collector<T, ?, List<Set<T>>> partitioning(int size) {
    class Acc {
        int count = 0;
        List<Set<T>> list = new ArrayList<>();

        void add(T elem) {
            int index = count++ / size;
            if (index == list.size()) list.add(new LinkedHashSet<>());
            list.get(index).add(elem);
        }

        Acc merge(Acc another) {
            another.list.stream().flatMap(Set::stream).forEach(this::add);
            return this;
        }
    }
    return Collector.of(Acc::new, Acc::add, Acc::merge, acc -> acc.list);
}

該方法接收每個分區的大小,並使用Acc本地類作為收集器使用的可變結構。 Acc類中,我使用的List將包含LinkedHashSet實例,它將保存流的元素。

Acc類保留已經收集的所有元素的計數。 add方法中,我計算列表的索引並遞增此計數,如果列表的該位置沒有設置,我向它添加一個新的空LinkedHashSet 然后,我將元素添加到集合中。

由於我在流上調用sorted()以在收集之前對其元素進行排序,因此我需要使用保留插入順序的數據結構。 這就是為什么我使用ArrayList作為外部列表,使用LinkedHashSet作為內部集合。

merge方法將由並行流使用,以合並兩個先前累積的Acc實例。 我只是通過委托add方法將收到的Acc實例的所有元素添加到此Acc實例中。

最后,我使用Collector.of基於Acc類的方法創建一個收集器。 最后一個參數是一個修整器函數, Acc返回Acc實例的列表。

如果你在類路徑上有guava ,這是一件輕而易舉的事:

        block
            .stream()
            .flatMap(Set::stream)
            .collect(Collectors.toCollection(TreeSet::new));

    Iterable<List<Integer>> result = Iterables.partition(sorted, 3);

添加另一個答案,因為這將比評論更大。 這確實是接受的答案所做的,但是使用“更智能”的組合器不需要一直流動。

 private static <T> Collector<T, ?, List<Set<T>>> partitioning(int size) {
    class Acc {
        int count = 0;

        List<List<T>> list = new ArrayList<>();

        void add(T elem) {
            int index = count++ / size;
            if (index == list.size()) {
                list.add(new ArrayList<>());
            }
            list.get(index).add(elem);
        }

        Acc merge(Acc right) {

            List<T> lastLeftList = list.get(list.size() - 1);
            List<T> firstRightList = right.list.get(0);
            int lastLeftSize = lastLeftList.size();
            int firstRightSize = firstRightList.size();

            // they have both the same size, simply addAll will work
            if (lastLeftSize + firstRightSize == 2 * size) {
                System.out.println("Perfect!");
                list.addAll(right.list);
                return this;
            }

            // last and first from each chunk are merged "perfectly"
            if (lastLeftSize + firstRightSize == size) {
                System.out.println("Almost perfect");
                int x = 0;
                while (x < firstRightSize) {
                    lastLeftList.add(firstRightList.remove(x));
                    --firstRightSize;
                }
                right.list.remove(0);
                list.addAll(right.list);
                return this;
            }

            right.list.stream().flatMap(List::stream).forEach(this::add);
            return this;
        }

        public List<Set<T>> finisher() {
            return list.stream().map(LinkedHashSet::new).collect(Collectors.toList());
        }

    }
    return Collector.of(Acc::new, Acc::add, Acc::merge, Acc::finisher);
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM