Java: bagaimana saya bisa membagi ArrayList dalam beberapa ArrayLists kecil?

201

Bagaimana saya bisa membagi ArrayList (ukuran = 1000) di beberapa ArrayLists dengan ukuran yang sama (= 10)?

ArrayList<Integer> results;
aneuryzm
sumber
1
Apakah Anda memerlukan tampilan atau koleksi baru?
xuesheng
2
Java 8: stackoverflow.com/a/51837311/1216775
akhil_mittal

Jawaban:

325

Kamu bisa memakai subList(int fromIndex, int toIndex) untuk mendapatkan sebagian dari daftar asli.

Dari API:

Mengembalikan tampilan porsi daftar ini antara yang ditentukan fromIndex, inklusif, dan toIndexeksklusif. (Jika fromIndexdan toIndexsama, daftar yang dikembalikan kosong.) Daftar yang dikembalikan didukung oleh daftar ini, sehingga perubahan non-struktural dalam daftar yang dikembalikan tercermin dalam daftar ini, dan sebaliknya. Daftar yang dikembalikan mendukung semua operasi daftar opsional yang didukung oleh daftar ini.

Contoh:

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

Jika Anda membutuhkan daftar cincang ini BUKAN tampilan, maka cukup buat yang baru Listdari subList. Berikut ini contoh menyatukan beberapa hal berikut:

// 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!)
polygenelubricants
sumber
213

Anda dapat menambahkan perpustakaan Guava ke proyek Anda dan menggunakan metode partisi Lists ., mis

List<Integer> bigList = ...
List<List<Integer>> smallerLists = Lists.partition(bigList, 10);
Mike Q
sumber
memodifikasi daftar sumber, sementara perulangan melalui sublists, Anda akan mendapatkan pengecualian bersamaan, karena statistik java doc: Daftar luar tidak dapat dimodifikasi, tetapi mencerminkan keadaan terbaru dari daftar sumber. Daftar dalam adalah tampilan sublist dari daftar asli. Ini
Junchen Liu
64

Apache Commons Collections 4 memiliki metode partisi di ListUtilskelas. Begini cara kerjanya:

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

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

Jawaban yang diberikan oleh polygenelubricants membagi array berdasarkan ukuran yang diberikan. Saya sedang mencari kode yang akan membagi array menjadi sejumlah bagian. Ini modifikasi yang saya lakukan pada kode:

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

Semoga ini bisa membantu seseorang.

Lara
sumber
14

Ini bekerja untuk saya

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

Misalnya:

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
sumber
3
tolong perhatikan ini memiliki bug yang mengabaikan kumpulan data terakhir. ex 201 dipecah menjadi potongan 100-an akan mengembalikan 100.100,0 bukannya 100.100,1
AAP
13

Java 8

Kami dapat membagi daftar berdasarkan beberapa ukuran atau berdasarkan suatu kondisi.

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

Maka kita bisa menggunakannya sebagai:

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
sumber
@i_am_zero Apakah mungkin menerapkan beberapa kondisi (metode statis ketiga) sehingga Anda dapat membuat beberapa daftar dari [[1,2,3,4], [5,6,7,8,9], [10,11,12 , 13,14]] dengan syarat: i <5, 5 <= i <10, i> = 10
gooornik07
2
@ gooornik07 stream hanya dapat digunakan sekali.
akhil_mittal
3

Saya menduga bahwa masalah yang Anda hadapi adalah dengan menyebutkan 100 ArrayLists dan mengisi mereka. Anda bisa membuat array ArrayLists dan mengisi masing-masing menggunakan loop.

Cara paling sederhana (baca paling bodoh) untuk melakukan ini adalah seperti ini:

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
sumber
3

Pertanyaan serupa didiskusikan di sini, Jawa: membagi Daftar menjadi dua sub-Daftar?

Terutama Anda dapat menggunakan sublist. Lebih detail di sini: subList

Mengembalikan tampilan porsi daftar ini antara fromIndex, inklusif, dan toIndex, eksklusif. (Jika dariIndex dan toIndex sama, daftar yang dikembalikan kosong.) Daftar yang dikembalikan didukung oleh daftar ini, sehingga perubahan dalam daftar yang dikembalikan tercermin dalam daftar ini, dan sebaliknya. Daftar yang dikembalikan mendukung semua operasi daftar opsional yang didukung oleh daftar ini ...

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

Contoh

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

    chunkArrayList(test,10);

Keluaran

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, 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, 89, 90 ], [91, 92, 93, 94, 95, 96, 97, 98, 99, 100], .........

Anda akan melihat di log Anda

pengguna3826696
sumber
3

Anda dapat menggunakan chunkmetode ini dari Eclipse Collections :

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

Beberapa contoh chunkmetode juga dimasukkan dalam artikel DZone ini .

Catatan: Saya pengendara untuk Eclipse Collections.

Donald Raab
sumber
2

Buat daftar baru dan tambahkan tampilan sublist dari daftar sumber menggunakan metode addAll untuk membuat daftar sublist baru
newList = new ArrayList (); newList.addAll (sourceList.subList (startIndex, endIndex));

pengguna688
sumber
1

Anda juga dapat menggunakan perpustakaan FunctionalJava - ada partitionmetode untuk List. Lib ini memiliki jenis koleksi sendiri, Anda dapat mengonversinya ke koleksi java bolak-balik.

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
sumber
Apakah ini membagi daftar Anda menjadi 2 Daftar atau 2 nilai per Daftar. Misalnya, jika daftar awal Anda adalah 10 elemen, ini akan menghasilkan 2 daftar 5 atau 5 daftar 2.
jDub9
@ jDub9 ini berfungsi seperti yang diperlukan dalam pertanyaan. Untuk 10 elemen, ia mengembalikan 5 daftar 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
sumber
0

jika Anda tidak ingin mengimpor pustaka apache commons coba kode sederhana ini:

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
sumber
@ Jaafar: Saya ingin yang sama seperti tetapi setelah 20 elemen dimuat cetak sekali lagi saya perlu memuat 20 elemen berikutnya dan seterusnya. Jadi tolong sarankan saya untuk ini.
vasantha
Hai @vasantha maaf saya tidak melihat permintaan Anda lebih awal, Anda sudah atau belum?
B.JAAFAR
0

Supaya jelas, Ini masih harus diuji lagi ...

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
sumber
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)

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

Akhil Sabu
sumber
-1

Anda perlu mengetahui ukuran chunk yang digunakan untuk membagi daftar Anda. Katakanlah Anda memiliki daftar 108 entriesdan Anda memerlukan ukuran chunk 25. Dengan demikian Anda akan berakhir dengan 5 lists:

  • 4 25 entriesmasing - masing memiliki ;
  • 1 (yang kelima) memiliki 8 elements.

Kode:

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
sumber