Sådan tælles duplikatelementer i Arraylist

1. Oversigt

I denne korte vejledning ser vi på nogle forskellige måder at tælle de duplikerede elementer i en ArrayList.

2. Loop med Map.put ()

Vores forventede resultat ville være et Kort objekt, som indeholder alle elementer fra inputlisten som taster og optællingen af ​​hvert element som værdi.

Den mest ligefremme løsning til at opnå dette ville være at løbe gennem inputlisten og for hvert element:

  • hvis den resultMap indeholder elementet, øger vi en tæller med 1
  • ellers, vi sætte en ny kortindgang (element, 1) til kortet
public Map countByClassicalLoop (List inputList) {Map resultMap = new HashMap (); for (T element: inputList) {if (resultMap.containsKey (element)) {resultMap.put (element, resultMap.get (element) + 1L); } andet {resultMap.put (element, 1L); }} returner resultMap; }

Denne implementering har den bedste kompatibilitet, da den fungerer for alle moderne Java-versioner.

Hvis vi ikke har brug for præ-Java 8-kompatibilitet, kan vi forenkle vores metode yderligere:

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

Lad os derefter oprette en inputliste for at teste metoden:

privat liste INPUT_LIST = Lists.list ("expect1", "expect2", "expect2", "expect3", "expect3", "expect3", "expect4", "expect4", "expect4", "expect4"); 

Og lad os nu kontrollere det:

privat ugyldighed verificereResult (Map resultMap) {assertThat (resultMap) .isNotEmpty (). hasSize (4) .containsExactly (entry ("expect1", 1L), entry ("expect2", 2L), entry ("expect3", 3L) , post ("expect4", 4L)); } 

Vi genbruger denne testsele resten af ​​vores tilgang.

3. Loop med Map.compute ()

I Java 8 er det praktisk beregne () metoden er blevet introduceret til Kort interface. Vi kan også bruge denne metode:

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

Varsel (k, v) -> v == null? 1L: v + 1L er remapping-funktionen, der implementerer BiFunction interface. For en given nøgle returnerer den enten den aktuelle værdi inkrementeret med en (hvis nøglen allerede findes på kortet) eller returnerer standardværdien for en.

For at gøre koden mere læselig, Vi kunne udtrække remapping-funktionen til dens variabel eller endda tage den som inputparameter for countByForEachLoopWithMapCompute.

4. Loop med Map.merge ()

Ved brug Map.compute (), vi skal håndtere nul værdier eksplicit - for eksempel hvis der ikke findes en kortlægning for en given nøgle. Derfor har vi implementeret en nul tjek vores omkortningsfunktion. Dette ser dog ikke smukt ud.

Lad os rydde op i vores kode yderligere ved hjælp af Map.merge () metode:

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

Nu ser koden ren og kortfattet ud.

Lad os forklare hvordan fusionere() arbejder. Hvis kortlægningen for en given nøgle ikke findes, eller hvis dens værdi er nul, den knytter nøglen til den angivne værdi. Ellers beregner den en ny værdi ved hjælp af remapping-funktionen og opdaterer kortlægningen i overensstemmelse hermed.

Bemærk, at vi brugte denne gang Lang :: sum som den BiFunction interface implementering.

5. Stream API Collectors.toMap ()

Da vi allerede har talt om Java 8, kan vi ikke glemme den kraftfulde Stream API. Takket være Stream API kan vi løse problemet på en meget kompakt måde.

Det at kortlægge() collector hjælper os med at konvertere inputlisten til en Kort:

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

Det at kortlægge() er en praktisk samler, som kan hjælpe os med at omdanne strømmen til forskellige Kort implementeringer.

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

Bortset fra at kortlægge(), vores problem kan løses af to andre samlere, gruppering af () og tæller ():

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

Korrekt brug af Java 8 Collectors gør vores kode kompakt og let at læse.

7. Konklusion

I denne hurtige artikel illustrerede vi forskellige måder at beregne antallet af duplikatelementer på en liste.

Hvis du gerne vil børste op på selve ArrayList, kan du tjekke referenceartiklen.

Som altid er den komplette kildekode tilgængelig på GitHub.


$config[zx-auto] not found$config[zx-overlay] not found