Java: split a List into two sub-Lists?

后端 未结 14 1515
执笔经年
执笔经年 2020-12-08 02:29

What\'s the simplest, most standard, and/or most efficient way to split a List into two sub-Lists in Java? It\'s OK to mutate the original List, so no copying should be nece

相关标签:
14条回答
  • 2020-12-08 02:48

    My solution:

    List<X> listToSplit = new ArrayList<X>();
    
    List<X> list1 = new ArrayList<X>();
    List<X> list2 = new ArrayList<X>();
    
    for (X entry : listToSplit)
    {
        if (list1.size () > list2.size ())
            list2.add (entry);
        else
            list1.add( entry );
    }
    

    Should work :)

    0 讨论(0)
  • 2020-12-08 02:51

    You can use common utilities, like Guava library:

    import com.google.common.collect.Lists;
    import com.google.common.math.IntMath;
    import java.math.RoundingMode;
    
    int partitionSize = IntMath.divide(list.size(), 2, RoundingMode.UP);
    List<List<T>> partitions = Lists.partition(list, partitionSize);
    

    The result is a list of two lists - not quite by your spec, but you can easily adapt, if needed.

    0 讨论(0)
  • 2020-12-08 02:53

    Quick semi-pseudo code:

    List sub=one.subList(...);
    List two=new XxxList(sub);
    sub.clear(); // since sub is backed by one, this removes all sub-list items from one
    

    That uses standard List implementation methods and avoids all the running around in loops. The clear() method is also going to use the internal removeRange() for most lists and be much more efficient.

    0 讨论(0)
  • 2020-12-08 02:53

    A solution using streams, partitioned using a toggle/flip boolean for each item:

    Collection<String> big = ...;
    AtomicBoolean switcheroo = new AtomicBoolean();
    Map<Boolean, List<String>> subLists = big.stream()
            .collect(Collectors.partitioningBy(o -> switcheroo.getAndSet(!switcheroo.get())));
    

    You end up with a map with two entries, keys are true and false and values are the sub-lists.

    This doesn't quite answer the original question, but you could use an AtomicInteger which increments each time, instead of an AtomicBoolean.

    0 讨论(0)
  • 2020-12-08 02:54

    sample java code to split List

    public List<List<Long>> split(List<Long> list, int i ){
    
        List<List<Long>> out = new ArrayList<List<Long>>();
    
        int size = list.size();
    
        int number = size/i;
        int remain = size % i; 
        if(remain != 0){
            number++;
        }
    
        for(int j=0; j < number; j++){
            int start  = j * i;
            int end =  start+ i;
            if(end > list.size()){
                end = list.size();
            }
            out.add(list.subList(start, end));
        }
    
        return out;
    }
    
    0 讨论(0)
  • 2020-12-08 02:56

    I needed something similar so this is my implementation. It allows the caller to specify which implementation of List should be returned:

    package com.mrojas.util;
    
    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.List;
    
    public class ListUtils {
    
    /**
     * Splits a list into smaller sublists.
     * The original list remains unmodified and changes on the sublists are not propagated to the original list.
     *
     *
     * @param original
     *            The list to split
     * @param maxListSize
     *            The max amount of element a sublist can hold.
     * @param listImplementation
     *            The implementation of List to be used to create the returned sublists
     * @return A list of sublists
     * @throws IllegalArgumentException
     *             if the argument maxListSize is zero or a negative number
     * @throws NullPointerException
     *             if arguments original or listImplementation are null
     */
    public static final <T> List<List<T>> split(final List<T> original, final int maxListSize,
            final Class<? extends List> listImplementation) {
        if (maxListSize <= 0) {
            throw new IllegalArgumentException("maxListSize must be greater than zero");
        }
    
        final T[] elements = (T[]) original.toArray();
        final int maxChunks = (int) Math.ceil(elements.length / (double) maxListSize);
    
        final List<List<T>> lists = new ArrayList<List<T>>(maxChunks);
        for (int i = 0; i < maxChunks; i++) {
            final int from = i * maxListSize;
            final int to = Math.min(from + maxListSize, elements.length);
            final T[] range = Arrays.copyOfRange(elements, from, to);
    
            lists.add(createSublist(range, listImplementation));
        }
    
        return lists;
    }
    
    /**
     * Splits a list into smaller sublists. The sublists are of type ArrayList.
     * The original list remains unmodified and changes on the sublists are not propagated to the original list.
     *
     *
     * @param original
     *            The list to split
     * @param maxListSize
     *            The max amount of element a sublist can hold.
     * @return A list of sublists
     */
    public static final <T> List<List<T>> split(final List<T> original, final int maxListSize) {
        return split(original, maxListSize, ArrayList.class);
    }
    
    private static <T> List<T> createSublist(final T[] elements, final Class<? extends List> listImplementation) {
        List<T> sublist;
        final List<T> asList = Arrays.asList(elements);
        try {
            sublist = listImplementation.newInstance();
            sublist.addAll(asList);
        } catch (final InstantiationException e) {
            sublist = asList;
        } catch (final IllegalAccessException e) {
            sublist = asList;
        }
    
        return sublist;
    }
    

    }

    And some test cases:

    package com.mrojas.util;
    
    import static org.junit.Assert.assertEquals;
    import static org.junit.Assert.assertTrue;
    
    import java.util.ArrayList;
    import java.util.Collections;
    import java.util.LinkedList;
    import java.util.List;
    
    import org.junit.Test;
    
    public class ListUtilsTest {
    
    @Test
    public void evenSplitTest() {
        final List<List<Object>> sublists = ListUtils.split(getPopulatedList(10), 2, LinkedList.class);
        assertEquals(5, sublists.size());
        for (final List<Object> sublist : sublists) {
            assertEquals(2, sublist.size());
            assertTrue(sublist instanceof LinkedList<?>);
        }
    }
    
    @Test
    public void unevenSplitTest() {
        final List<List<Object>> sublists = ListUtils.split(getPopulatedList(10), 3, LinkedList.class);
        assertEquals(4, sublists.size());
    
        assertEquals(3, sublists.get(0).size());
        assertEquals(3, sublists.get(1).size());
        assertEquals(3, sublists.get(2).size());
        assertEquals(1, sublists.get(3).size());
    }
    
    @Test
    public void greaterThanSizeSplitTest() {
        final List<List<Object>> sublists = ListUtils.split(getPopulatedList(10), 20, LinkedList.class);
        assertEquals(1, sublists.size());
        assertEquals(10, sublists.get(0).size());
    }
    
    @Test
    public void emptyListSplitTest() {
        final List<List<Object>> sublists = ListUtils.split(Collections.emptyList(), 10, LinkedList.class);
        assertEquals(0, sublists.size());
    }
    
    @Test(expected=IllegalArgumentException.class)
    public void negativeChunkSizeTest() {
        ListUtils.split(getPopulatedList(5), -10, LinkedList.class);
    }
    
    @Test
    public void invalidClassTest() {
        final List<List<Object>> sublists = ListUtils.split(getPopulatedList(10), 2, LinkedList.class);
        assertEquals(5, sublists.size());
        for (final List<Object> sublist : sublists) {
            assertEquals(2, sublist.size());
            assertTrue(sublist instanceof LinkedList<?>);
        }
    }
    
    private List<Object> getPopulatedList(final int size) {
        final List<Object> list = new ArrayList<Object>(10);
        for (int i = 0; i < 10; i++) {
            list.add(new Object());
        }
    
        return list;
    }
    

    }

    0 讨论(0)
提交回复
热议问题