Java 8: How to turn a list into a list of lists using lambda

I am trying to split a list into a list where each list has a maximum size of 4.

I would like to know how to do this using lambdas.

I am currently doing this:

List<List<Object>> listOfList = new ArrayList<>();

final int MAX_ROW_LENGTH = 4;
int startIndex =0;
while(startIndex <= listToSplit.size() )    
{
    int endIndex = ( ( startIndex+MAX_ROW_LENGTH ) <  listToSplit.size() ) ? startIndex+MAX_ROW_LENGTH : listToSplit.size();
    listOfList.add(new ArrayList<>(listToSplit.subList(startIndex, endIndex)));
    startIndex = startIndex+MAX_ROW_LENGTH;
}

UPDATE

There seems to be no easy way to use lambdas to split lists. While all answers are much appreciated, they are also a great example of when lambdas don't simplify things.

+6
source share
5 answers

Try this approach:

    static <T> List<List<T>> listSplitter(List<T> incoming, int size) {
    // add validation if needed
    return incoming.stream()
            .collect(Collector.of(
                    ArrayList::new,
                    (accumulator, item) -> {
                        if(accumulator.isEmpty()) {
                            accumulator.add(new ArrayList<>(singletonList(item)));
                        } else {
                            List<T> last = accumulator.get(accumulator.size() - 1);
                            if(last.size() == size) {
                                accumulator.add(new ArrayList<>(singletonList(item)));
                            } else {
                                last.add(item);
                            }
                        }
                    },
                    (li1, li2) -> {
                        li1.addAll(li2);
                        return li1;
                    }
            ));
}

    System.out.println(
            listSplitter(
                    Arrays.asList(0, 1, 2, 3, 4, 5, 6, 7, 8, 9),
                    4
            )
    );

Also note that this code can be optimized, rather than:

new ArrayList<>(Collections.singletonList(item))

use this one:

List<List<T>> newList = new ArrayList<>(size);
newList.add(item);
return newList;
+3
source

, . .

    List<List<Object>> lists = new ArrayList<>();
    AtomicInteger counter = new AtomicInteger();
    final int MAX_ROW_LENGTH = 4;
    listToSplit.forEach(pO -> {
        if(counter.getAndIncrement() % MAX_ROW_LENGTH == 0) {
            lists.add(new ArrayList<>());
        }
        lists.get(lists.size()-1).add(pO);
    });
+3

, :

final int[] counter = new int[] {0};

List<List<Object>> listOfLists = in.stream()
   .collect(Collectors.groupingBy( x -> counter[0]++ / MAX_ROW_LENGTH ))
   .entrySet().stream()
   .sorted(Map.Entry.comparingByKey())
   .map(Map.Entry::getValue)
   .collect(Collectors.toList());

, groupingBy, lambda mapSupplier SortedMap. EntrySet, . .

:

  • Map<Integer,Object>, . , , final.
  • Integer.
  • Stream::map() Map.Entry<Integer,Object> Object.
  • .

"" . Map . .


, . - :

for(int i=0; i<in.size(); i += MAX_ROW_LENGTH) {
    listOfList.add(
        listToSplit.subList(i, Math.min(i + MAX_ROW_LENGTH, in.size());
}

( new ArrayList<>(listToSplit.subList(...)). , - , , , , .)

. .


( ) List, List<Object>:

public class PartitionedList<T> extends AbstractList<List<T>> {

    private final List<T> source;
    private final int sublistSize;

    public PartitionedList(T source, int sublistSize) {
       this.source = source;
       this.sublistSize = sublistSize;
    }

    @Override
    public int size() {
       return source.size() / sublistSize;
    }

    @Override
    public List<T> get(int index) {
       int sourceIndex = index * sublistSize
       return source.subList(sourceIndex, 
                             Math.min(sourceIndex + sublistSize, source.size());
    }
}

, , .

.

+2

, -

 BiFunction<List,Integer,List> splitter= (list2, count)->{
            //temporary list of lists
            List<List> listOfLists=new ArrayList<>();

            //helper implicit recursive function
            BiConsumer<Integer,BiConsumer> splitterHelper = (offset, func) -> {
                if(list2.size()> offset+count){
                    listOfLists.add(list2.subList(offset,offset+count));

                    //implicit self call
                    func.accept(offset+count,func);
                }
                else if(list2.size()>offset){
                    listOfLists.add(list2.subList(offset,list2.size()));

                    //implicit self call
                    func.accept(offset+count,func);
                }
            };

            //pass self reference
            splitterHelper.accept(0,splitterHelper);

            return listOfLists;
        };

List<Integer> list=new ArrayList<Integer>(){{
            add(1);
            add(2);
            add(3);
            add(4);
            add(5);
            add(6);
            add(7);
            add(8);
            add(8);
        }};

        //calling splitter function
        List listOfLists = splitter.apply(list, 3 /*max sublist size*/);

        System.out.println(listOfLists);

[[1, 2, 3], [4, 5, 6], [7, 8, 8]]
+2

,

final List<List<Object>> listOfList = new ArrayList<>(
            listToSplit.stream()
                    .collect(Collectors.groupingBy(el -> listToSplit.indexOf(el) / MAX_ROW_LENGTH))
                    .values()
    );

, : β†’ , (map.values ​​() Collection, ).

0

All Articles