Java: Wie kann ich eine ArrayList in mehrere kleine ArrayLists aufteilen?

200

Wie kann ich eine ArrayList (Größe = 1000) in mehrere ArrayLists derselben Größe (= 10) aufteilen?

ArrayList<Integer> results;
aneuryzm
quelle
1
Benötigen Sie Ansichten oder neue Sammlungen?
Xuesheng
2
Java 8: stackoverflow.com/a/51837311/1216775
akhil_mittal

Antworten:

324

Sie können verwenden subList(int fromIndex, int toIndex), um eine Ansicht eines Teils der ursprünglichen Liste zu erhalten.

Aus der API:

Gibt eine Ansicht des Teils dieser Liste zwischen den angegebenen fromIndex, inklusive und toIndexexklusiven zurück. (Wenn fromIndexund toIndexgleich sind, ist die zurückgegebene Liste leer.) Die zurückgegebene Liste wird von dieser Liste unterstützt, sodass nicht strukturelle Änderungen in der zurückgegebenen Liste in dieser Liste berücksichtigt werden und umgekehrt. Die zurückgegebene Liste unterstützt alle optionalen Listenoperationen, die von dieser Liste unterstützt werden.

Beispiel:

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]"

Wenn Sie diese gehackten Listen NICHT als Ansicht benötigen, erstellen Sie einfach eine neue Listaus dem subList. Hier ist ein Beispiel für die Zusammenstellung einiger dieser Dinge:

// 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!)
Polygenschmierstoffe
quelle
213

Sie können die Guava- Bibliothek zu Ihrem Projekt hinzufügen und die Methode Lists.partition verwenden, z

List<Integer> bigList = ...
List<List<Integer>> smallerLists = Lists.partition(bigList, 10);
Mike Q.
quelle
Ändern Sie die Quellliste, während Sie die Unterlisten durchlaufen, erhalten Sie eine gleichzeitige Ausnahme, da Java Doc-Statistiken: Die äußere Liste kann nicht geändert werden, spiegelt jedoch den neuesten Status der Quellliste wider. Die inneren Listen sind Unterlistenansichten der ursprünglichen Liste. Dies ist
Junchen Liu
64

Apache Commons Collections 4 verfügt über eine Partitionsmethode in der ListUtilsKlasse. So funktioniert das:

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

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

Die Antwort von Polygenschmierstoffen teilt ein Array basierend auf der angegebenen Größe auf. Ich suchte nach Code, der ein Array in eine bestimmte Anzahl von Teilen aufteilt. Hier ist die Änderung, die ich am Code vorgenommen habe:

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;
}

Hoffe es hilft jemandem.

Lara
quelle
14

Das funktioniert bei mir

/**
* 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()-1 : i + chunkSize));
    }
    return chunkList;
}

Z.B :

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);
JR
quelle
3
Bitte beachten Sie, dass dies einen Fehler hat, der den letzten Datensatz ignoriert. Ex 201, aufgeteilt in 100er-Stücke, gibt 100.100,0 statt 100.100,1 zurück
AAP
13

Java 8

Wir können eine Liste basierend auf einer bestimmten Größe oder basierend auf einer Bedingung aufteilen.

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();
}

Dann können wir sie verwenden als:

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]]
akhil_mittal
quelle
@i_am_zero Ist es möglich, mehrere Bedingungen anzuwenden (dritte statische Methode), sodass Sie mehrere Listen erstellen können, z. B. [[1,2,3,4], [5,6,7,8,9], [10,11,12 , 13,14]] unter Bedingungen: i <5, 5 <= i <10, i> = 10
gooornik07
2
@ gooornik07 ein stream kann nur einmal verwendet werden.
akhil_mittal
3

Ich vermute, dass das Problem darin besteht, 100 ArrayLists zu benennen und zu füllen. Sie können ein Array von ArrayLists erstellen und diese mit einer Schleife füllen.

Der einfachste (dümmste) Weg, dies zu tun, ist folgender:

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));
    } 
angstrom91
quelle
3

Eine ähnliche Frage wurde hier diskutiert, Java: Eine Liste in zwei Unterlisten aufteilen?

Hauptsächlich können Sie Unterlisten verwenden. Weitere Details hier: Unterliste

Gibt eine Ansicht des Teils dieser Liste zwischen fromIndex (einschließlich) und toIndex (exklusiv) zurück. (Wenn fromIndex und toIndex gleich sind, ist die zurückgegebene Liste leer.) Die zurückgegebene Liste wird von dieser Liste unterstützt, sodass Änderungen in der zurückgegebenen Liste in dieser Liste berücksichtigt werden und umgekehrt. Die zurückgegebene Liste unterstützt alle optionalen Listenoperationen, die von dieser Liste unterstützt werden ...

Inkognito
quelle
3
private ArrayList<List<String>> chunkArrayList(ArrayList<String> arrayToChunk, int chunkSize) {
    ArrayList<List<String>> chunkList = new ArrayList<>();
    int guide = arrayToChunk.size();
    int index = 0;
    int tale = chunkSize;
    while (tale < arrayToChunk.size()){
            chunkList.add(arrayToChunk.subList(index, tale));
            guide = guide - chunkSize;
            index = index + chunkSize;
            tale = tale + chunkSize;
    }
    if (guide >0) {
       chunkList.add(arrayToChunk.subList(index, index + guide));
    }
    Log.i("Chunked Array: " , chunkList.toString());
    return chunkList;
}

Beispiel

    ArrayList<String> test = new ArrayList<>();
    for (int i=1; i<=1000; i++){
        test.add(String.valueOf(i));
    }

    chunkArrayList(test,10);

Ausgabe

CHUNKED :: [[1, 2, 3, 4, 5, 6, 7, 8, 9, 10], [11, 12, 13, 14, 15, 16, 17, 18, 19, 20], [21 22, 23, 24, 25, 26, 27, 28, 29, 30], [31, 32, 33, 34, 35, 36, 37, 38, 39, 40], [41, 42, 43, 44 45, 46, 47, 48, 49, 50], [51, 52, 53, 54, 55, 56, 57, 58, 59, 60], [61, 62, 63, 64, 65, 66, 67 68, 69, 70], [71, 72, 73, 74, 75, 76, 77, 78, 79, 80], [81, 82, 83, 84, 85, 86, 87, 88, 89, 90 ], [91, 92, 93, 94, 95, 96, 97, 98, 99, 100], .........

Sie werden in Ihrem Protokoll sehen

user3826696
quelle
3

Sie können die chunkMethode aus Eclipse-Sammlungen verwenden :

ArrayList<Integer> list = new ArrayList<>(Interval.oneTo(1000));
RichIterable<RichIterable<Integer>> chunks = Iterate.chunk(list, 10);
Verify.assertSize(100, chunks);

Einige Beispiele für die chunkMethode wurden ebenfalls in diesen DZone-Artikel aufgenommen .

Hinweis: Ich bin ein Committer für Eclipse-Sammlungen.

Donald Raab
quelle
2

Erstellen Sie eine neue Liste und fügen Sie mit der Methode addAll eine Unterlistenansicht der
Quellliste hinzu, um eine neue Unterlistenliste zu erstellen. NewList = new ArrayList (); newList.addAll (sourceList.subList (startIndex, endIndex));

user688
quelle
1

Sie können auch die FunctionalJava- Bibliothek verwenden - es gibt eine partitionMethode für List. Diese Bibliothek hat ihre eigenen Sammlungstypen. Sie können sie hin und her in Java-Sammlungen konvertieren.

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);
Mikhail Golubtsov
quelle
Teilt dies Ihre Liste in 2 Listen oder 2 Werte pro Liste auf? Wenn Ihre ursprüngliche Liste beispielsweise 10 Elemente enthält, ergibt dies 2 Listen mit 5 oder 5 Listen mit 2.
jDub9
@ jDub9 dies funktioniert wie es in der Frage erforderlich ist. Für 10 Elemente gibt es 5 Listen von 2 zurück. Github.com/functionaljava/functionaljava/blob/…
Mikhail Golubtsov
1
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++;
}
Rahul Palakurthi
quelle
0

Wenn Sie die Apache Commons-Bibliothek nicht importieren möchten, versuchen Sie diesen einfachen 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;
}
B.JAAFAR
quelle
@Jaafar: Ich möchte das gleiche wie, aber nachdem 20 Elemente geladen wurden, muss ich die nächsten 20 Elemente laden und so weiter. Bitte schlagen Sie mich dafür vor.
Vasantha
Hallo @vasantha Entschuldigung, ich habe deine Anfrage nicht früh gesehen, hast du es getan oder noch nicht?
B.JAAFAR
0

Nur um klar zu sein, das muss noch mehr getestet werden ...

public class Splitter {

public static <T> List<List<T>> splitList(List<T> listTobeSplit, int size) {
    List<List<T>> sublists= new LinkedList<>();
    if(listTobeSplit.size()>size) {
    int counter=0;
    boolean lastListadded=false;

    List<T> subList=new LinkedList<>();

    for(T t: listTobeSplit) {           
         if (counter==0) {               
             subList =new LinkedList<>();
             subList.add(t);
             counter++;
             lastListadded=false;
         }
         else if(counter>0 && counter<size-1) {
             subList.add(t);
             counter++;
         }
         else {
             lastListadded=true;
             subList.add(t);
             sublists.add(subList);
             counter=0;
         }              
    }
    if(lastListadded==false)
        sublists.add(subList);      
    }
    else {
        sublists.add(listTobeSplit);
    }
    log.debug("sublists: "+sublists);
    return sublists;
 }
}
Vikky
quelle
0
    **Divide a list to lists of n size**

    import java.util.AbstractList;
    import java.util.ArrayList;
    import java.util.List;

    public final class PartitionUtil<T> extends AbstractList<List<T>> {

        private final List<T> list;
        private final int chunkSize;

        private PartitionUtil(List<T> list, int chunkSize) {
            this.list = new ArrayList<>(list);
            this.chunkSize = chunkSize;
        }

        public static <T> PartitionUtil<T> ofSize(List<T> list, int chunkSize) {
            return new PartitionUtil<>(list, chunkSize);
        }

        @Override
        public List<T> get(int index) {
            int start = index * chunkSize;
            int end = Math.min(start + chunkSize, list.size());

            if (start > end) {
                throw new IndexOutOfBoundsException("Index " + index + " is out of the list range <0," + (size() - 1) + ">");
            }

            return new ArrayList<>(list.subList(start, end));
        }

        @Override
        public int size() {
            return (int) Math.ceil((double) list.size() / (double) chunkSize);
        }
    }





Function call : 
              List<List<String>> containerNumChunks = PartitionUtil.ofSize(list, 999)

Weitere Details: https://e.printstacktrace.blog/divide-a-list-to-lists-of-n-size-in-Java-8/

Akhil Sabu
quelle
-1

Sie müssen die Blockgröße kennen, durch die Sie Ihre Liste teilen. Angenommen, Sie haben eine Liste von 108 entriesund Sie benötigen eine Blockgröße von 25. So erhalten Sie 5 lists:

  • 4 mit 25 entriesjeweils;
  • 1 (der fünfte) mit 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());
        }
    }
Yogesh Kumar
quelle