Cara Mengira Elemen Pendua dalam Arraylist

1. Gambaran keseluruhan

Dalam tutorial ringkas ini, kita akan melihat beberapa cara yang berbeza untuk menghitung unsur-unsur pendua dalam ArrayList .

2. Gelung dengan Map.put ()

Hasil yang kami harapkan adalah objek Peta , yang berisi semua elemen dari senarai input sebagai kunci dan jumlah setiap elemen sebagai nilai.

Penyelesaian yang paling mudah untuk mencapai ini adalah mencari senarai input dan untuk setiap elemen:

  • jika resultMap mengandungi elemen, kita menambah pembilang dengan 1
  • jika tidak, kami meletakkan entri peta baru (elemen, 1) ke peta
public  Map countByClassicalLoop(List inputList) { Map resultMap = new HashMap(); for (T element : inputList) { if (resultMap.containsKey(element)) { resultMap.put(element, resultMap.get(element) + 1L); } else { resultMap.put(element, 1L); } } return resultMap; }

Pelaksanaan ini mempunyai keserasian terbaik, kerana ia berfungsi untuk semua versi Java moden.

Sekiranya kita tidak memerlukan keserasian pra-Java 8, kita dapat mempermudah kaedah kita lebih jauh:

public  Map countByForEachLoopWithGetOrDefault(List inputList) { Map resultMap = new HashMap(); inputList.forEach(e -> resultMap.put(e, resultMap.getOrDefault(e, 0L) + 1L)); return resultMap; }

Seterusnya, mari buat senarai input untuk menguji kaedah:

private List INPUT_LIST = Lists.list( "expect1", "expect2", "expect2", "expect3", "expect3", "expect3", "expect4", "expect4", "expect4", "expect4"); 

Dan sekarang mari kita mengesahkannya:

private void verifyResult(Map resultMap) { assertThat(resultMap) .isNotEmpty().hasSize(4) .containsExactly( entry("expect1", 1L), entry("expect2", 2L), entry("expect3", 3L), entry("expect4", 4L)); } 

Kami akan menggunakan kembali kaedah ujian ini untuk sisa pendekatan kami.

3. Gelung dengan Map.compute ()

Di Java 8, kaedah komputasi berguna () telah diperkenalkan ke antara muka Peta . Kita boleh menggunakan kaedah ini juga:

public  Map countByForEachLoopWithMapCompute(List inputList) { Map resultMap = new HashMap(); inputList.forEach(e -> resultMap.compute(e, (k, v) -> v == null ? 1L : v + 1L)); return resultMap; }

Perhatikan (k, v) -> v == null? 1L: v + 1L adalah fungsi pemetaan semula yang melaksanakan antara muka BiFunction . Untuk kunci yang diberikan, ia mengembalikan nilai semasa yang ditingkatkan oleh satu (jika kunci sudah ada di peta) atau mengembalikan nilai lalai dari satu.

Untuk membuat kod lebih mudah dibaca, kita dapat mengekstrak fungsi pemetaan semula ke pembolehubahnya atau bahkan menjadikannya sebagai parameter input untuk countByForEachLoopWithMapCompute.

4. Gelung dengan Map.merge ()

Semasa menggunakan Map.compute () , kita harus menangani nilai nol secara eksplisit - misalnya, jika pemetaan untuk kunci tertentu tidak ada. Inilah sebabnya mengapa kami melaksanakan pemeriksaan nol dalam fungsi pemetaan semula kami. Walau bagaimanapun, ini tidak kelihatan cantik.

Mari bersihkan kod kami lebih jauh dengan bantuan kaedah Map.merge () :

public  Map countByForEachLoopWithMapMerge(List inputList) { Map resultMap = new HashMap(); inputList.forEach(e -> resultMap.merge(e, 1L, Long::sum)); return resultMap; }

Kini kodnya kelihatan bersih dan ringkas.

Mari terangkan bagaimana penggabungan () berfungsi. Sekiranya pemetaan untuk kunci yang diberikan tidak ada, atau nilainya nol , ia mengaitkan kunci dengan nilai yang diberikan. Jika tidak, ia mengira nilai baru menggunakan fungsi pemetaan semula dan mengemas kini pemetaan dengan sewajarnya.

Perhatikan bahawa kali ini kami menggunakan Long :: sum sebagai pelaksanaan antara muka BiFunction .

5. Stream API Pengumpul. ke Peta ()

Oleh kerana kita sudah bercakap mengenai Java 8, kita tidak dapat melupakan Stream API yang hebat. Terima kasih kepada Stream API, kami dapat menyelesaikan masalah dengan cara yang sangat padat.

The toMap () pengumpul membantu kita untuk menukar senarai input ke dalam Peta :

public  Map countByStreamToMap(List inputList) { return inputList.stream().collect(Collectors.toMap(Function.identity(), v -> 1L, Long::sum)); }

The toMap () adalah pengumpul yang mudah, yang boleh membantu kita untuk mengubah aliran ke dalam berbeza Peta pelaksanaan.

6. Stream API Collectors.groupingBy () dan Collectors.counting ()

Kecuali untuk toMap () , masalah kami dapat diselesaikan oleh dua pengumpul lain, mengelompokkanBy () dan mengira () :

public  Map countByStreamGroupBy(List inputList) { return inputList.stream().collect(Collectors.groupingBy(k -> k, Collectors.counting())); }

Penggunaan Java 8 Collectors yang betul menjadikan kod kami ringkas dan mudah dibaca.

7. Kesimpulannya

Dalam artikel ringkas ini, kami menggambarkan pelbagai cara untuk mengira jumlah unsur pendua dalam satu senarai.

Sekiranya anda ingin mengetahui ArrayList itu sendiri, anda boleh menyemak artikel rujukannya.

Seperti biasa, kod sumber lengkap boleh didapati di GitHub.