Java: how can I split an ArrayList in multiple sma

2019-01-01 13:13发布

问题:

How can I split an ArrayList (size=1000) in multiple ArrayLists of the same size (=10) ?

ArrayList<Integer> results;

回答1:

You can use subList(int fromIndex, int toIndex) to get a view of a portion of the original list.

From the API:

Returns a view of the portion of this list between the specified fromIndex, inclusive, and toIndex, exclusive. (If fromIndex and toIndex are equal, the returned list is empty.) The returned list is backed by this list, so non-structural changes in the returned list are reflected in this list, and vice-versa. The returned list supports all of the optional list operations supported by this list.

Example:

List<Integer> numbers = new ArrayList<Integer>(
    Arrays.asList(5,3,1,2,9,5,0,7)
);

List<Integer> head = numbers.subList(0, 4);
List<Integer> tail = numbers.subList(4, 8);
System.out.println(head); // prints \"[5, 3, 1, 2]\"
System.out.println(tail); // prints \"[9, 5, 0, 7]\"

Collections.sort(head);
System.out.println(numbers); // prints \"[1, 2, 3, 5, 9, 5, 0, 7]\"

tail.add(-1);
System.out.println(numbers); // prints \"[1, 2, 3, 5, 9, 5, 0, 7, -1]\"

If you need these chopped lists to be NOT a view, then simply create a new List from the subList. Here\'s an example of putting a few of these things together:

// chops a list into non-view sublists of length L
static <T> List<List<T>> chopped(List<T> list, final int L) {
    List<List<T>> parts = new ArrayList<List<T>>();
    final int N = list.size();
    for (int i = 0; i < N; i += L) {
        parts.add(new ArrayList<T>(
            list.subList(i, Math.min(N, i + L)))
        );
    }
    return parts;
}


List<Integer> numbers = Collections.unmodifiableList(
    Arrays.asList(5,3,1,2,9,5,0,7)
);
List<List<Integer>> parts = chopped(numbers, 3);
System.out.println(parts); // prints \"[[5, 3, 1], [2, 9, 5], [0, 7]]\"
parts.get(0).add(-1);
System.out.println(parts); // prints \"[[5, 3, 1, -1], [2, 9, 5], [0, 7]]\"
System.out.println(numbers); // prints \"[5, 3, 1, 2, 9, 5, 0, 7]\" (unmodified!)


回答2:

You can add the Guava library to your project and use the Lists.partition method, e.g.

List<Integer> bigList = ...
List<List<Integer>> smallerLists = Lists.partition(bigList, 10);


回答3:

Apache Commons Collections 4 has a partition method in the ListUtils class. Here’s how it works:

import org.apache.commons.collections4.ListUtils;
...

int targetSize = 100;
List<Integer> largeList = ...
List<List<Integer>> output = ListUtils.partition(largeList, targetSize);


回答4:

The answer provided by polygenelubricants splits an array based on given size. I was looking for code that would split an array into a given number of parts. Here is the modification I did to the code:

public static <T>List<List<T>> chopIntoParts( final List<T> ls, final int iParts )
{
    final List<List<T>> lsParts = new ArrayList<List<T>>();
    final int iChunkSize = ls.size() / iParts;
    int iLeftOver = ls.size() % iParts;
    int iTake = iChunkSize;

    for( int i = 0, iT = ls.size(); i < iT; i += iTake )
    {
        if( iLeftOver > 0 )
        {
            iLeftOver--;

            iTake = iChunkSize + 1;
        }
        else
        {
            iTake = iChunkSize;
        }

        lsParts.add( new ArrayList<T>( ls.subList( i, Math.min( iT, i + iTake ) ) ) );
    }

    return lsParts;
}

Hope it helps someone.



回答5:

This works for me

/**
* Returns List of the List argument passed to this function with size = chunkSize
* 
* @param largeList input list to be portioned
* @param chunkSize maximum size of each partition
* @param <T> Generic type of the List
* @return A list of Lists which is portioned from the original list 
*/
public static  <T> List<List<T>> chunkList(List<T> list, int chunkSize) {
    if (chunkSize <= 0) {
        throw new IllegalArgumentException(\"Invalid chunk size: \" + chunkSize);
    }
    List<List<T>> chunkList = new ArrayList<>(list.size() / chunkSize);
    for (int i = 0; i < list.size(); i += chunkSize) {
        chunkList.add(list.subList(i, i + chunkSize >= list.size() ? list.size() : i + chunkSize));
    }
    return chunkList;
}

Eg :

List<Integer> stringList = new ArrayList<>();
stringList.add(0);
stringList.add(1);
stringList.add(2);
stringList.add(3);
stringList.add(4);
stringList.add(5);
stringList.add(6);
stringList.add(7);
stringList.add(8);
stringList.add(9);

List<List<Integer>> chunkList = getChunkList1(stringList, 2);


回答6:

I\'m guessing that the issue you\'re having is with naming 100 ArrayLists and populating them. You can create an array of ArrayLists and populate each of those using a loop.

The simplest (read stupidest) way to do this is like this:

ArrayList results = new ArrayList(1000);
    // populate results here
    for (int i = 0; i < 1000; i++) {
        results.add(i);
    }
    ArrayList[] resultGroups = new ArrayList[100];
    // initialize all your small ArrayList groups
    for (int i = 0; i < 100; i++) {
            resultGroups[i] = new ArrayList();
    }
    // put your results into those arrays
    for (int i = 0; i < 1000; i++) {
       resultGroups[i/10].add(results.get(i));
    } 


回答7:

A similar question was discussed here, Java: split a List into two sub-Lists?

Mainly you can use sublist. More details here : subList

Returns a view of the portion of this list between fromIndex, inclusive, and toIndex, exclusive. (If fromIndex and toIndex are equal, the returned list is empty.) The returned list is backed by this list, so changes in the returned list are reflected in this list, and vice-versa. The returned list supports all of the optional list operations supported by this list...



回答8:

Create a new list and add sublist view of source list using addAll method to create a new sublist
List newList = new ArrayList(); newList.addAll(sourceList.subList(startIndex, endIndex));



回答9:

You can also use FunctionalJava library - there is partition method for List. This lib has its own collection types, you can convert them to java collections back and forth.

import fj.data.List;

java.util.List<String> javaList = Arrays.asList(\"a\", \"b\", \"c\", \"d\" );

List<String> fList = Java.<String>Collection_List().f(javaList);

List<List<String> partitions = fList.partition(2);


回答10:

import org.apache.commons.collections4.ListUtils;
ArrayList<Integer> mainList = .............;
List<List<Integer>> multipleLists = ListUtils.partition(mainList,100);
int i=1;
for (List<Integer> indexedList : multipleLists){
  System.out.println(\"Values in List \"+i);
  for (Integer value : indexedList)
    System.out.println(value);
i++;
}


回答11:

Java 8

We can split a list based on some size or based on a condition.

static Collection<List<Integer>> partitionIntegerListBasedOnSize(List<Integer> inputList, int size) {
        return inputList.stream()
                .collect(Collectors.groupingBy(s -> (s-1)/size))
                .values();
}
static <T> Collection<List<T>> partitionBasedOnSize(List<T> inputList, int size) {
        final AtomicInteger counter = new AtomicInteger(0);
        return inputList.stream()
                    .collect(Collectors.groupingBy(s -> counter.getAndIncrement()/size))
                    .values();
}
static <T> Collection<List<T>> partitionBasedOnCondition(List<T> inputList, Predicate<T> condition) {
        return inputList.stream().collect(Collectors.partitioningBy(s-> (condition.test(s)))).values();
}

Then we can use them as:

final List<Integer> list = Arrays.asList(1,2,3,4,5,6,7,8,9,10);
System.out.println(partitionIntegerListBasedOnSize(list, 4));  // [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10]]
System.out.println(partitionBasedOnSize(list, 4));  // [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10]]
System.out.println(partitionBasedOnSize(list, 3));  // [[1, 2, 3], [4, 5, 6], [7, 8, 9], [10]]
System.out.println(partitionBasedOnCondition(list, i -> i<6));  // [[6, 7, 8, 9, 10], [1, 2, 3, 4, 5]]


回答12:

if you don\'t want to import the apache commons library try this simple code:

final static int MAX_ELEMENT = 20;

public static void main(final String[] args) {

    final List<String> list = new ArrayList<String>();

    for (int i = 1; i <= 161; i++) {
        list.add(String.valueOf(i));
        System.out.print(\",\" + String.valueOf(i));
    }
    System.out.println(\"\");
    System.out.println(\"### >>> \");
    final List<List<String>> result = splitList(list, MAX_ELEMENT);

    for (final List<String> entry : result) {
        System.out.println(\"------------------------\");
        for (final String elm : entry) {
            System.out.println(elm);
        }
        System.out.println(\"------------------------\");
    }

}

private static List<List<String>> splitList(final List<String> list, final int maxElement) {

    final List<List<String>> result = new ArrayList<List<String>>();

    final int div = list.size() / maxElement;

    System.out.println(div);

    for (int i = 0; i <= div; i++) {

        final int startIndex = i * maxElement;

        if (startIndex >= list.size()) {
            return result;
        }

        final int endIndex = (i + 1) * maxElement;

        if (endIndex < list.size()) {
            result.add(list.subList(startIndex, endIndex));
        } else {
            result.add(list.subList(startIndex, list.size()));
        }

    }

    return result;
}


回答13:

You need to know the chunk size by which you\'re dividing your list. Say you have a list of 108 entries and you need a chunk size of 25. Thus you will end up with 5 lists:

  • 4 having 25 entries each;
  • 1 (the fifth) having 8 elements.

Code:

public static void main(String[] args) {

        List<Integer> list = new ArrayList<Integer>();
        for (int i=0; i<108; i++){
            list.add(i);
        }
        int size= list.size();
        int j=0;
                List< List<Integer> > splittedList = new ArrayList<List<Integer>>()  ;
                List<Integer> tempList = new ArrayList<Integer>();
        for(j=0;j<size;j++){
            tempList.add(list.get(j));
        if((j+1)%25==0){
            // chunk of 25 created and clearing tempList
            splittedList.add(tempList);
            tempList = null;
            //intializing it again for new chunk 
            tempList = new ArrayList<Integer>();
        }
        }
        if(size%25!=0){
            //adding the remaining enteries 
            splittedList.add(tempList);
        }
        for (int k=0;k<splittedList.size(); k++){
            //(k+1) because we started from k=0
            System.out.println(\"Chunk number: \"+(k+1)+\" has elements = \"+splittedList.get(k).size());
        }
    }