Bagaimana Menghitung Elemen Duplikat di Arraylist

1. Ikhtisar

Dalam tutorial singkat ini, kita akan melihat beberapa cara berbeda untuk menghitung elemen duplikat dalam ArrayList .

2. Loop dengan Map.put ()

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

Solusi paling mudah untuk mencapai ini adalah dengan mengulang melalui daftar input dan untuk setiap elemen:

  • jika resultMap berisi elemen, kita menambah penghitung sebesar 1
  • jika tidak, kita 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; }

Implementasi ini memiliki kompatibilitas terbaik, karena berfungsi untuk semua versi Java modern.

Jika kami tidak memerlukan kompatibilitas pra-Java 8, kami dapat menyederhanakan metode kami lebih lanjut:

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

Selanjutnya, mari buat daftar input untuk menguji metode:

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

Dan sekarang mari kita verifikasi:

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 test harness ini untuk sisa pendekatan kami.

3. Loop dengan Map.compute ()

Di Java 8, metode compute () praktis telah diperkenalkan ke antarmuka Peta . Kita juga dapat menggunakan metode ini:

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 ulang yang mengimplementasikan antarmuka BiFunction . Untuk kunci tertentu, ia akan mengembalikan nilai saat ini ditambah satu (jika kunci sudah ada di peta) atau mengembalikan nilai default satu.

Untuk membuat kode lebih mudah dibaca, kita dapat mengekstrak fungsi pemetaan ulang ke variabelnya atau bahkan menjadikannya sebagai parameter input untuk countByForEachLoopWithMapCompute.

4. Ulangi dengan Map.merge ()

Saat menggunakan Map.compute () , kita harus menangani nilai null secara eksplisit - misalnya, jika pemetaan untuk kunci yang diberikan tidak ada. Inilah mengapa kami menerapkan pemeriksaan nol dalam fungsi pemetaan ulang kami. Ini, bagaimanapun, tidak terlihat bagus.

Mari bersihkan kode kita lebih jauh dengan bantuan metode Map.merge () :

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

Sekarang kodenya terlihat bersih dan ringkas.

Mari kita jelaskan cara kerja merge () . Jika pemetaan untuk kunci tertentu tidak ada, atau nilainya null , kunci tersebut akan dikaitkan dengan nilai yang diberikan. Jika tidak, itu menghitung nilai baru menggunakan fungsi pemetaan ulang dan memperbarui pemetaan yang sesuai.

Perhatikan bahwa kali ini kami menggunakan Long :: sum sebagai implementasi antarmuka BiFunction .

5. Stream API Collectors.toMap ()

Karena kita sudah membicarakan Java 8, kita tidak bisa melupakan API Stream yang kuat. Berkat API Stream, kami dapat menyelesaikan masalah dengan cara yang sangat ringkas.

The toMap () kolektor membantu kita untuk mengubah daftar masukan ke dalam Peta :

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

The toMap () adalah kolektor nyaman, yang dapat membantu kita untuk mengubah sungai menjadi berbeda Peta implementasi.

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

Kecuali untuk toMap () , masalah kita dapat diselesaikan oleh dua kolektor lain, groupingBy () dan count () :

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

Penggunaan yang tepat dari Java 8 Collectors membuat kode kami kompak dan mudah dibaca.

7. Kesimpulan

Dalam artikel singkat ini, kami mengilustrasikan berbagai cara untuk menghitung jumlah elemen duplikat dalam daftar.

Jika Anda ingin memoles ArrayList itu sendiri, Anda dapat melihat artikel referensi.

Seperti biasa, kode sumber lengkap tersedia di GitHub.