Elementen verwijderen uit Java-verzamelingen

1. Overzicht

In deze korte tutorial, we gaan het hebben over vier verschillende manieren om items uit Java te verwijderen Collecties die overeenkomen met bepaalde predikaten.

We zullen natuurlijk ook enkele kanttekeningen bekijken.

2. Onze collectie definiëren

Eerst gaan we twee benaderingen illustreren die de oorspronkelijke datastructuur muteren. Vervolgens zullen we het hebben over twee andere opties die in plaats van de items te verwijderen, een kopie van het origineel maken Verzameling zonder hen.

Laten we de volgende verzameling in onze voorbeelden gebruiken om te demonstreren hoe we hetzelfde resultaat kunnen bereiken met verschillende methoden:

Verzamelingsnamen = nieuwe ArrayList (); names.add ("John"); names.add ("Ana"); names.add ("Mary"); names.add ("Anthony"); names.add ("Mark");

3. Elementen verwijderen met Iterator

Java's Iterator stelt ons in staat om elk individueel element binnen een te lopen en te verwijderen Verzameling.

Om dit te doen, moeten we eerst een iterator over zijn elementen ophalen met behulp van de iterator methode. Daarna kunnen we elk element bezoeken met behulp van De volgende en verwijder ze met verwijderen:

Iterator i = names.iterator (); while (i.hasNext ()) {String e = i.next (); if (e.startsWith ("A")) {i.remove (); }}

Ondanks zijn eenvoud zijn er enkele kanttekeningen waarmee we rekening moeten houden:

  • Afhankelijk van de collectie kunnen we tegenkomen ConcurrentModificationException uitzonderingen
  • We moeten de elementen herhalen voordat we ze kunnen verwijderen
  • Afhankelijk van de collectie, verwijderen kan zich anders gedragen dan verwacht. Bijv .: ArrayList.Iterator verwijdert het element uit de verzameling en verschuift daaropvolgende gegevens naar links, terwijl, LinkedList.Iterator past eenvoudig de aanwijzer aan naar het volgende element. Als zodanig, LinkedList.Iterator presteert veel beter dan ArrayList.Iterator bij het verwijderen van items

4. Java 8 en Collection.removeIf ()

Java 8 introduceerde een nieuwe methode voor de Verzameling interface die een beknoptere manier biedt om elementen te verwijderen met Predikaat:

names.removeIf (e -> e.startsWith ("A"));

Het is belangrijk op te merken dat in tegenstelling tot de Iterator nadering, removeIf presteert in beide even goed LinkedList en ArrayList.

In Java 8, ArrayList overschrijft de standaardimplementatie - die afhankelijk is van Iterator - en implementeert een andere strategie: eerst itereert het over de elementen en markeert degene die overeenkomen met onze Predikaat; daarna herhaalt het een tweede keer om de elementen te verwijderen (en te verschuiven) die in de eerste iteratie waren gemarkeerd.

5. Java 8 en de introductie van Stroom

Een van de nieuwe belangrijke functies in Java 8 was de toevoeging van Stroom (en Verzamelaars). Er zijn veel manieren om een Stroom van een bron. De meeste bewerkingen die van invloed zijn op het Stroom instantie zal de bron niet muteren, maar de API richt zich op het maken van kopieën van een bron en het uitvoeren van elke bewerking die we daarin nodig hebben.

Laten we eens kijken hoe we het kunnen gebruiken Stroom en Verzamelaars om elementen te vinden / filteren die wel en niet overeenkomen met ons Predikaat.

5.1. Elementen verwijderen met Stroom

Verwijderen, of liever gezegd, filterende elementen met Stroom is vrij eenvoudig, we hoeven alleen een instantie van Stroom met behulp van onze Verzameling, beroep doen op filter met onze Predikaat en dan verzamelen het resultaat met behulp van Verzamelaars:

Collectie filterCollection = namen .stream () .filter (e ->! E.startsWith ("A")) .collect (Collectors.toList ());

Streamen is minder invasief dan de vorige benaderingen, bevordert isolatie en maakt het mogelijk om meerdere kopieën van dezelfde bron te maken. We moeten er echter rekening mee houden dat het ook het geheugen vergroot dat door onze applicatie wordt gebruikt.

5.2. Collectors.partitioningBy

Beide combineren Stream.filter en Verzamelaars is best handig, hoewel we kunnen scenario's tegenkomen waarin we zowel overeenkomende als niet-overeenkomende elementen nodig hebben. In dergelijke gevallen kunnen we profiteren van Collectors.partitioningBy:

Kaart ClassifiedElements = names .stream () .collect (Collectors.partitioningBy ((String e) ->! e.startsWith ("A"))); String matching = String.join (",", classElements.get (true)); String nonMatching = String.join (",", classElements.get (false));

Deze methode retourneert een Kaart die slechts twee sleutels bevat, waar en false, elk wijzend naar een lijst die respectievelijk de overeenkomende en niet-overeenkomende elementen bevat.

6. Conclusie

In dit artikel hebben we gekeken naar enkele methoden om elementen uit te verwijderen Collecties en enkele van hun kanttekeningen.

Je kunt de volledige broncode en alle codefragmenten voor dit artikel vinden op GitHub.


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