Partition a List di Java

1. Gambaran keseluruhan

Dalam tutorial ini saya akan menerangkan bagaimana membahagikan Senarai menjadi beberapa senarai dari ukuran tertentu.

Untuk operasi yang agak sederhana, tidak ada sokongan dalam API pengumpulan Java standard. Nasib baik, kedua Jambu dan Koleksi Apache Commons telah melaksanakan operasi dengan cara yang serupa.

Artikel ini adalah sebahagian daripada siri " Java - Back to Basic " di Baeldung.

2. Gunakan Jambu biji untuk membahagikan Senarai

Jambu batu memudahkan pembahagian Senarai ke subsenarai saiz yang ditetapkan - via yang Lists.partition operasi :

@Test public void givenList_whenParitioningIntoNSublists_thenCorrect() { List intList = Lists.newArrayList(1, 2, 3, 4, 5, 6, 7, 8); List
    
      subSets = Lists.partition(intList, 3); List lastPartition = subSets.get(2); List expectedLastPartition = Lists. newArrayList(7, 8); assertThat(subSets.size(), equalTo(3)); assertThat(lastPartition, equalTo(expectedLastPartition)); }
    

3. Gunakan Jambu Batu untuk Membahagi Koleksi

Mempersembahkan Koleksi juga boleh dilakukan dengan Jambu:

@Test public void givenCollection_whenParitioningIntoNSublists_thenCorrect() { Collection intCollection = Lists.newArrayList(1, 2, 3, 4, 5, 6, 7, 8); Iterable
    
      subSets = Iterables.partition(intCollection, 3); List firstPartition = subSets.iterator().next(); List expectedLastPartition = Lists. newArrayList(1, 2, 3); assertThat(firstPartition, equalTo(expectedLastPartition)); }
    

Perlu diingat bahawa partisi adalah paparan sublist dari koleksi asal - yang bermaksud bahawa perubahan dalam koleksi asal akan ditunjukkan dalam partisi:

@Test public void givenListPartitioned_whenOriginalListIsModified_thenPartitionsChangeAsWell() { // Given List intList = Lists.newArrayList(1, 2, 3, 4, 5, 6, 7, 8); List
    
      subSets = Lists.partition(intList, 3); // When intList.add(9); // Then List lastPartition = subSets.get(2); List expectedLastPartition = Lists. newArrayList(7, 8, 9); assertThat(lastPartition, equalTo(expectedLastPartition)); }
    

4. Gunakan Koleksi Apache Commons untuk membahagikan Senarai

Keluaran terbaru dari Koleksi Apache Commons baru-baru ini telah menambahkan sokongan untuk membahagikan Senarai juga:

@Test public void givenList_whenParitioningIntoNSublists_thenCorrect() { List intList = Lists.newArrayList(1, 2, 3, 4, 5, 6, 7, 8); List
    
      subSets = ListUtils.partition(intList, 3); List lastPartition = subSets.get(2); List expectedLastPartition = Lists. newArrayList(7, 8); assertThat(subSets.size(), equalTo(3)); assertThat(lastPartition, equalTo(expectedLastPartition)); }
    

Tidak ada pilihan yang sesuai untuk membagi Koleksi mentah - serupa dengan Guava Iterables.partition dalam Commons Collections.

Akhirnya, peringatan yang sama berlaku di sini juga - partisi yang dihasilkan adalah pandangan dari Senarai asal.

5. Gunakan Java8 untuk Mempartisi Senarai

Sekarang, mari kita lihat bagaimana menggunakan Java8 untuk membahagikan Senarai kita.

5.1. Pembahagian pemungutDengan

Kita boleh menggunakan Collectors.partitioningBy () untuk memisahkan senarai menjadi 2 sublists - seperti berikut:

@Test public void givenList_whenParitioningIntoSublistsUsingPartitionBy_thenCorrect() { List intList = Lists.newArrayList(1, 2, 3, 4, 5, 6, 7, 8); Map
    
      groups = intList.stream().collect(Collectors.partitioningBy(s -> s > 6)); List
     
       subSets = new ArrayList
      
       (groups.values()); List lastPartition = subSets.get(1); List expectedLastPartition = Lists. newArrayList(7, 8); assertThat(subSets.size(), equalTo(2)); assertThat(lastPartition, equalTo(expectedLastPartition)); }
      
     
    

Catatan: Partisi yang dihasilkan bukan pandangan dari senarai utama, jadi perubahan yang berlaku pada Senarai utama tidak akan mempengaruhi partisi.

5.2. Pengumpul groupingBy

Kami juga boleh menggunakan Collectors.groupingBy () untuk memisahkan senarai kami kepada beberapa partisi:

@Test public final void givenList_whenParitioningIntoNSublistsUsingGroupingBy_thenCorrect() { List intList = Lists.newArrayList(1, 2, 3, 4, 5, 6, 7, 8); Map
    
      groups = intList.stream().collect(Collectors.groupingBy(s -> (s - 1) / 3)); List
     
       subSets = new ArrayList
      
       (groups.values()); List lastPartition = subSets.get(2); List expectedLastPartition = Lists. newArrayList(7, 8); assertThat(subSets.size(), equalTo(3)); assertThat(lastPartition, equalTo(expectedLastPartition)); }
      
     
    

Catatan: Sama seperti Collectors.partitioningBy () - partisi yang dihasilkan tidak akan dipengaruhi oleh perubahan dalam senarai utama.

5.3. Pisahkan Senarai mengikut Pemisah

Kami juga dapat menggunakan Java8 untuk membagi Daftar kami dengan pemisah:

@Test public void givenList_whenSplittingBySeparator_thenCorrect() { List intList = Lists.newArrayList(1, 2, 3, 0, 4, 5, 6, 0, 7, 8); int[] indexes = Stream.of(IntStream.of(-1), IntStream.range(0, intList.size()) .filter(i -> intList.get(i) == 0), IntStream.of(intList.size())) .flatMapToInt(s -> s).toArray(); List
    
      subSets = IntStream.range(0, indexes.length - 1) .mapToObj(i -> intList.subList(indexes[i] + 1, indexes[i + 1])) .collect(Collectors.toList()); List lastPartition = subSets.get(2); List expectedLastPartition = Lists. newArrayList(7, 8); assertThat(subSets.size(), equalTo(3)); assertThat(lastPartition, equalTo(expectedLastPartition)); }
    

Catatan: Kami menggunakan "0" sebagai pemisah - pertama kami memperoleh indeks semua elemen "0" dalam Senarai, kemudian kami membagi Senarai pada indeks ini.

6. Kesimpulannya

Penyelesaian yang dikemukakan di sini menggunakan perpustakaan tambahan - Jambu atau perpustakaan Apache Commons Collections. Kedua-duanya sangat ringan dan sangat berguna secara keseluruhan, jadi masuk akal untuk memiliki salah satu dari mereka di lorong kelas; namun, jika itu bukan pilihan - penyelesaian hanya Java ditunjukkan di sini.

Pelaksanaan semua contoh dan coretan kod ini dapat dilihat di GitHub - ini adalah projek berasaskan Maven, jadi mudah untuk diimport dan dijalankan sebagaimana adanya.