Java: comment diviser une ArrayList en plusieurs petites ArrayLists?

201

Comment puis-je diviser une liste de tableaux (taille = 1000) en plusieurs listes de tableaux de même taille (= 10)?

ArrayList<Integer> results;
anévrisme
la source
1
Besoin de vues ou de nouvelles collections?
xuesheng
2
Java 8: stackoverflow.com/a/51837311/1216775
akhil_mittal

Réponses:

325

Vous pouvez utiliser subList(int fromIndex, int toIndex)pour obtenir une vue d'une partie de la liste d'origine.

Depuis l'API:

Renvoie une vue de la partie de cette liste entre le spécifié fromIndex, inclusif et toIndexexclusif. (Si fromIndexet toIndexsont égaux, la liste renvoyée est vide.) La liste renvoyée est soutenue par cette liste, donc les modifications non structurelles de la liste renvoyée sont reflétées dans cette liste, et vice-versa. La liste renvoyée prend en charge toutes les opérations de liste facultatives prises en charge par cette liste.

Exemple:

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

Si vous avez besoin que ces listes hachées ne soient PAS une vue, créez simplement une nouvelle à Listpartir de subList. Voici un exemple de regroupement de quelques-unes de ces choses:

// 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!)
polygénelubrifiants
la source
213

Vous pouvez ajouter la bibliothèque Guava à votre projet et utiliser la méthode Lists.partition , par exemple

List<Integer> bigList = ...
List<List<Integer>> smallerLists = Lists.partition(bigList, 10);
Mike Q
la source
modifier la liste source, tout en parcourant les sous-listes, vous obtiendrez une exception simultanée, car java doc stats: La liste externe n'est pas modifiable, mais reflète le dernier état de la liste source. Les listes internes sont des vues de sous-liste de la liste d'origine. C'est
Junchen Liu
64

Apache Commons Collections 4 a une méthode de partition dans la ListUtilsclasse. Voici comment ça fonctionne:

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

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

La réponse fournie par les lubrifiants polygéniques divise un tableau en fonction de la taille donnée. Je cherchais du code qui diviserait un tableau en un nombre donné de parties. Voici la modification que j'ai apportée au 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;
}

J'espère que cela aide quelqu'un.

Lara
la source
14

Ça marche pour moi

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

Par exemple :

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
la source
3
veuillez noter que cela a un bug qui ignore le dernier ensemble de données. ex 201 divisé en morceaux de 100 renverra 100,100,0 au lieu de 100,100,1
AAP
13

Java 8

Nous pouvons diviser une liste en fonction d'une certaine taille ou en fonction d'une 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();
}

Ensuite, nous pouvons les utiliser comme:

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
la source
@i_am_zero Est-il possible d'appliquer plusieurs conditions (troisième méthode statique) afin de pouvoir créer plusieurs listes ex [[1,2,3,4], [5,6,7,8,9], [10,11,12 , 13,14]] sous conditions: i <5, 5 <= i <10, i> = 10
gooornik07
2
@ gooornik07 un flux ne peut être utilisé qu'une seule fois.
akhil_mittal
3

Je suppose que le problème que vous rencontrez est de nommer 100 listes de tableaux et de les remplir. Vous pouvez créer un tableau de listes de tableaux et remplir chacun de ceux-ci à l'aide d'une boucle.

La façon la plus simple (à lire la plus stupide) de procéder est la suivante:

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
la source
3

Une question similaire a été discutée ici, Java: diviser une liste en deux sous-listes?

Vous pouvez principalement utiliser la sous-liste. Plus de détails ici: subList

Renvoie une vue de la partie de cette liste entre fromIndex, inclus et toIndex, exclusif. (Si fromIndex et toIndex sont égaux, la liste renvoyée est vide.) La liste renvoyée est soutenue par cette liste, donc les changements dans la liste retournée sont reflétés dans cette liste, et vice-versa. La liste renvoyée prend en charge toutes les opérations de liste facultatives prises en charge par cette liste ...

Incognito
la source
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;
}

Exemple

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

    chunkArrayList(test,10);

Production

RÉPARTI :: [[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], .........

vous verrez dans votre journal

user3826696
la source
3

Vous pouvez utiliser la chunkméthode des collections Eclipse :

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

Quelques exemples de la chunkméthode ont également été inclus dans cet article DZone .

Remarque: je suis un committer pour les collections Eclipse.

Donald Raab
la source
2

Créez une nouvelle liste et ajoutez une vue de sous-liste de la liste source en utilisant la méthode addAll pour créer une nouvelle liste de sous-
liste newList = new ArrayList (); newList.addAll (sourceList.subList (startIndex, endIndex));

user688
la source
1

Vous pouvez également utiliser la bibliothèque FunctionalJava - il existe une partitionméthode pour List. Cette bibliothèque a ses propres types de collection, vous pouvez les convertir en collections java dans les deux sens.

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
la source
Est-ce que cela divise votre liste en 2 listes ou 2 valeurs par liste. Par exemple, si votre liste initiale était de 10 éléments, cela donnerait-il 2 listes de 5 ou 5 listes de 2.
jDub9
@ jDub9 cela fonctionne comme il est requis dans la question. Pour 10 éléments, il renvoie 5 listes de 2. 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
la source
0

si vous ne voulez pas importer la bibliothèque apache commons, essayez ce code simple:

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
la source
@Jaafar: Je veux la même chose, mais après 20 éléments chargés, imprimer, encore une fois, je dois charger les 20 éléments suivants et ainsi de suite. Veuillez donc me suggérer pour cela.
vasantha
Salut @vasantha désolé, je n'ai pas vu votre demande tôt, vous l'avez fait ou pas encore?
B.JAAFAR
0

Juste pour être clair, cela doit encore être testé plus ...

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
la source
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)

plus de détails: https://e.printstacktrace.blog/divide-a-list-to-lists-of-n-size-in-Java-8/

Akhil Sabu
la source
-1

Vous devez connaître la taille des morceaux par lesquels vous divisez votre liste. Supposons que vous ayez une liste 108 entrieset que vous ayez besoin d'une taille de morceau de 25. Ainsi vous vous retrouverez avec 5 lists:

  • 4 ayant 25 entrieschacun;
  • 1 (le cinquième) ayant 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
la source