4

here is my list:

List<Integer> mylist = Arrays.asList(1,2,3,4,5,6,7,8,9,10,11,12);

Assuming my list is always even, then i would like to split it in 6 equal parts.

List as a Sketch:

[1,2,3,4,5,6,7,8,9,10,11,12]

Output Sketch:

[[1,2][3,4],[5,6],[7,8],[9,10],[11,12]]

I would prefer a solution if possible with Java 8 stream flatMap

Mureinik
  • 297,002
  • 52
  • 306
  • 350
Andre Proenza
  • 149
  • 1
  • 10

5 Answers5

5

Given that the "sublists" are all of equal size and that you can divide the list into exact sublists of the same size, you could calculate the desired size and then map an IntStream to the starting indexes of each sublist and use that to extract them:

List<Integer> mylist = Arrays.asList(1,2,3,4,5,6,7,8,9,10,11,12);
int size = mylist.size();
int parts = 6;
int partSize = size / parts;
List<List<Integer>> result = 
    IntStream.range(0, parts)
             .mapToObj(i -> mylist.subList(i * partSize, (i + 1) * partSize)))
             .collect(Collectors.toList());

EDIT:
IdeOne demo graciously provided by @Turing85

Mureinik
  • 297,002
  • 52
  • 306
  • 350
2

I know it out of the scope but another possibility is using a library like Guava which has a lot of methods related to List.

Dependency

<dependency>
    <groupId>com.google.guava</groupId>
    <artifactId>guava</artifactId>
    <version>30.1-jre</version>
</dependency>

Example

package com.stackoverflow.question;

import java.util.Arrays;
import java.util.List;

import com.google.common.collect.Lists;

public class Question {
    public static void main(String[] args) {
        List<Integer> mylist = Arrays.asList(1,2,3,4,5,6,7,8,9,10,11,12);
        List<List<Integer>> partionList = Lists.partition(mylist, 2);
        
        System.out.println(partionList);
    }
}

Output

[[1, 2], [3, 4], [5, 6], [7, 8], [9, 10], [11, 12]]
Andres Sacco
  • 650
  • 3
  • 13
1

Stream-operations should be stateless. The task to perform inherently needs state. Thus, I would recommend not using Stream. Instead, I would recommend a for-loop based solution:

public static List<List<Integer>> partition(
        List<Integer> list, 
        int partitionSize) {
    final int listSize = list.size();
    if (listSize % partitionSize != 0) {
        throw new IllegalArgumentException("The size of the list must be "
                + "divisible without remainder by the partition size.");
    }
    
    final List<List<Integer>> partition = new ArrayList<>();
    for (int start = 0; start < listSize; start += partitionSize) {
        partition.add(list.subList(start, start + partitionSize));
    }
    return partition;
}

Ideone demo

If we insist on using a Stream-based implementation, I would suggest using the code presented Mureinik's answer.

Turing85
  • 18,217
  • 7
  • 33
  • 58
0

The following will work for any group size from 1 to the size of the list. If the group size does not evenly divided the list size then the remainder will be put into their own group.

Also, the extra map(ArrayList::new) ensures the sublist is put in its own list. Otherwise, changing the original list entries will also change the sublist entries.

int gsize = 2;
List<Integer> mylist =
        Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12);
    List<List<Integer>> subLists = IntStream
            .iterate(0, i -> i < mylist.size(),
                    i -> i + gsize)
            .mapToObj(i -> mylist.subList(i,
                    (i + gsize <= mylist.size()) ?
                            i + gsize : mylist.size()))
            .map(ArrayList::new)
            .collect(Collectors.toList());
    
System.out.println(subLists);

Prints

[[1, 2], [3, 4], [5, 6], [7, 8], [9, 10], [11, 12]]

If the group size was 5, the new list would look like the following:

[[1, 2, 3, 4, 5], [6, 7, 8, 9, 10], [11, 12]]
WJS
  • 36,363
  • 4
  • 24
  • 39
0

If you truly want a solution with flatMap, you can try something like this, not an intuitive solution though. At the end it only need to return a Stream, so this is simply constructing sub lists as it progress and returning it as Stream at the end.

btw, I personally prefer Guava's Lists.partition

List result = list.stream().flatMap(new Function<>() {

                 List<List<Integer>> mainList = new ArrayList<>();
                 List<Integer> subList = new ArrayList<>(2);
                 int index = 0;

                 @Override
                 public Stream<?> apply(Integer integer) {
                     subList.add(integer);

                     if ((index + 1) % 2 == 0) {
                         mainList.add(subList);
                         subList = new ArrayList<>(2);
                     }
                     index++;
                     if (index == list.size()) {
                         if(!subList.isEmpty()) {
                             mainList.add(subList);
                         }
                         return mainList.stream();
                     }
                     return Stream.empty();
                 }

             }).collect(Collectors.toList());
Janardhan
  • 89
  • 3