Home > Back-end >  What is the best way to collect [0..n], [n 1..l] elements in separate sets using Java 8 streams?
What is the best way to collect [0..n], [n 1..l] elements in separate sets using Java 8 streams?

Time:10-11

I have a HashSet, I need to collect [0..n] elements in one HashSet and [n 1...l] elements in another HashSet using Java 8 streams. Where n >=0 is an arbitrary number, l >=0 is the length of given HashSet.

resultSet1 = set.stream()
.limit(n)
.collect(Collectors.toSet());

The above gives me [0..n] elements. I could again call stream() and then skip(), but the thing is HashSet in java is unordered, so there is a probability that the skip method skips the element which was not collected above.

resultSet2 = set.stream()
.skip(n)
.collect(Collectors.toSet());

I can use traditional for, but a solution using streams will be great.

E.g. given set = {1,2,3,4,5} resultSet1 = {1,2} resultSet2 = {3,4,5}

CodePudding user response:

Here is a way to solve this problem

Set firstSet = set.stream()
                  .limit(n)
                  .collect(toSet());

Set secondSet = new HashSet<>(set);
secondSet.removeAll(firstSet);

A second way would be

AtomicInteger atomicInteger = new AtomicInteger();
Set<Integer> set = Set.of(1, 2, 3, 4, 5);
int n = 2;

Map<Boolean, Set<Integer>> map = 
     set.stream()
        .collect(
             Collectors.partitioningBy(
                 $ -> atomicInteger.addAndGet(1) > n), 
                 Collectors.toSet()
        );

CodePudding user response:

Use partitioningBy() with a toSet() downstream collector:

int[] i = {0}; // the array is "effectively final"
Map<Boolean, Set<Integer>> map = set.stream()
  .collect(Collectors.partitioningBy(x -> i[0]   < n, toSet()));

You can use a int[], which is effectively final, to hold the counter referenced within the lambda, which may mutate its contents.

  • Related