How to sort a list of TreeSets with java8 threads

My list has kits like [1,3,5][2,6,4] etc., all the same size. I tried to do this, but it does not work.

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

Final result: [1,2,3][4,5,6] .

I could try adding all the elements to an ArrayList and sorting them, then creating a new List from the TreeSet . But is there any one liner?

UPDATE:

 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()); 

It works, but can it be simplified?

+7
java java-8 java-stream treeset
source share
3 answers

@ Eugene answer is sweet because Guava is sweet. But if you do not have Guava in your class path, here is another way:

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

Firstly, I collect all the sets into a single stream, then sort all the elements and finally collect the entire sorted stream into a list of sets. To do this, I call a helper method that uses a custom collector:

 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); } 

The method gets the size of each section and uses the local Acc class as a mutable structure that will be used by the collector. Inside the Acc class, I use a List that will contain instances of LinkedHashSet that will contain the elements of the stream.

The Acc class contains an account of all the elements that are already assembled. In the add method, I calculate the index of the list and increase it, and if there was no set at that position in the list, I add a new empty LinkedHashSet to it. Then I add the item to the set.

Since I call sorted() on the stream to sort its elements before collecting, I need to use data structures that preserve the insertion order. This is why I use ArrayList for the external list and LinkedHashSet for the internal sets.

The merge method must be used by parallel threads to combine two previously accumulated Acc instances. I simply add all the elements of the resulting Acc instance to this Acc instance by delegating the add method.

Finally, I use Collector.of to create a collector based on the methods of the Acc class. The final argument is the finisher function, which simply returns a list of Acc instances.

+10
source share

If you have guava in the classpath, this is a breeze:

  block .stream() .flatMap(Set::stream) .collect(Collectors.toCollection(TreeSet::new)); Iterable<List<Integer>> result = Iterables.partition(sorted, 3); 
+3
source share

Adding another answer as this will be more comment. This is really what the accepted answer did, but with a β€œsmarter” combiner that doesn't have to constantly flow again.

  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); } 
+3
source share

All Articles