CodeGym/Java-blogg/Tilfeldig/Slette et element fra en ArrayList
John Squirrels
Nivå
San Francisco

Slette et element fra en ArrayList

Publisert i gruppen
Hei! I siste leksjon ble vi kjent med klassen ArrayList, og lærte hvordan vi utfører de vanligste operasjonene med denne klassen. I tillegg påpekte vi flere forskjeller mellom en ArrayListog en ordinær matrise. Men vi gikk over ett emne, nemlig hvordan du sletter elementer fra en ArrayList. Vi skal diskutere det nå. Slette et element fra en ArrayList - 1Vi har allerede nevnt at det ikke er veldig praktisk å slette elementer fra en vanlig matrise. Siden vi ikke kan slette selve elementet, kan vi bare "nulle ut" (sett til null) verdien:
public class Cat {

   private String name;

   public Cat(String name) {
       this.name = name;
   }

   public static void main(String[] args) {

       Cat[] cats = new Cat[3];
       cats[0] = new Cat("Thomas");
       cats[1] = new Cat("Behemoth");
       cats[2] = new Cat("Lionel Messi");

       cats[1] = null;

       System.out.println(Arrays.toString(cats));
   }


@Override
   public String toString() {
       return "Cat{" +
               "name='" + name + '\'' +
               '}';
   }
}
Utdata: [Cat{name='Thomas'}, null, Cat{name='Lionel Messi'}] Men å sette et array-element til null etterlater et "hull". Vi har ikke fjernet posisjonen i matrisen, bare innholdet. Tenk deg hva som ville skje hvis vi hadde en rekke med 50 katter og fjernet 17 av dem på denne måten. Vi vil ha en matrise med 17 hull. Bare prøv å holde styr på dem! Det er urealistisk å forvente å huske antall tomme celler der du kan skrive nye verdier. Hvis du gjør en feil, vil du overskrive en objektreferanse du ønsker. Det er selvfølgelig en måte å gjøre dette litt mer forsiktig på: etter at du har fjernet et element, flytter du elementene til fronten av matrisen for å sette "hullet" på slutten:
public static void main(String[] args) {

   Cat[] cats = new Cat[4];
   cats[0] = new Cat("Thomas");
   cats[1] = new Cat("Behemoth");
   cats[2] = new Cat("Lionel Messi");
   cats[2] = new Cat("Fluffy");

   cats[1] = null;

   for (int i = 2; i < cats.length-1; i++) {
       cats [i-1] = cats [i];// Move the elements to the front of the array, so the empty position is at the end
   }

   System.out.println(Arrays.toString(cats));
}
Utdata: [Cat{name='Thomas'}, Cat{name='Fluffy'}, Cat{name='Fluffy'}, null] Dette virker bedre, men det kan neppe kalles en robust løsning. Om ikke annet enn det faktum at vi må skrive denne koden hver gang vi sletter et element fra en matrise! Dette er et dårlig alternativ. Vi kan gå en annen vei og lage en egen metode:
public void deleteCat(Cat[] cats, int indexToDelete) {
   //...delete the cat corresponding to the index and move the elements
}
Men dette er også til liten nytte: denne metoden kan bare fungere med Catobjekter, men ikke andre typer. Med andre ord, hvis et program har ytterligere 100 klasser som vi ønsker å bruke med matriser, må vi skrive den samme metoden med nøyaktig samme logikk i hver av dem. Dette er en total katastrofe -_- Men ArrayListklassen løser dette problemet! Den implementerer en spesiell metode for å fjerne elementer:remove()
public static void main(String[] args) {

   ArrayList<Cat> cats = new ArrayList<>();
   Cat thomas = new Cat("Thomas");
   Cat behemoth = new Cat("Behemoth");
   Cat lionel = new Cat("Lionel Messi");
   Cat fluffy = new Cat ("Fluffy");

   cats.add(thomas);
   cats.add(behemoth);
   cats.add(lionel);
   cats.add(fluffy);
   System.out.println(cats.toString());

   cats.remove(1);

   System.out.println(cats.toString());
}
Vi sender objektets indeks til metoden, som sletter den (akkurat som i en matrise). Metoden remove()har to spesielle egenskaper. For det første etterlater den ikke "hull". Den implementerer allerede logikken som trengs for å skifte elementer når et element fjernes fra midten, som vi tidligere skrev selv. Se på utdataene fra forrige kode:
[Cat{name='Thomas'}, Cat{name='Behemoth'}, Cat{name='Lionel Messi'}, Cat{name='Fluffy'}]

[Cat{name='Thomas'}, Cat{name='Lionel Messi'}, Cat{name='Fluffy'}]
Vi fjernet en katt fra midten, og resten ble flyttet slik at det ikke ble tomme plasser. For det andre kan den slette objekter ikke bare etter indeks (som en vanlig matrise), men også ved referanse :
public static void main(String[] args) {

   ArrayList<Cat> cats = new ArrayList<>();
   Cat thomas = new Cat("Thomas");
   Cat behemoth = new Cat("Behemoth");
   Cat lionel = new Cat("Lionel Messi");
   Cat fluffy = new Cat ("Fluffy");

   cats.add(thomas);
   cats.add(behemoth);
   cats.add(lionel);
   cats.add(fluffy);
   System.out.println(cats.toString());

   cats.remove(lionel);

   System.out.println(cats.toString());
}
Utdata: [Cat{name='Thomas'}, Cat{name='Behemoth'}, Cat{name='Lionel Messi'}, Cat{name='Fluffy'}] [Cat{name='Thomas'}, Cat{name='Behemoth'}, Cat{name='Fluffy'}] Dette kan være veldig praktisk hvis du ikke alltid vil holde styr på det ønskede objektets indeks. Det ser ut til at vi har funnet ut vanlig sletting. La oss nå forestille oss denne situasjonen: vi ønsker å iterere over listen vår og fjerne en katt med et spesifikt navn . For å gjøre dette bruker vi en rask forloop (også kalt en for-hver-løkke), som vi ble introdusert for i Rishis leksjoner:
public static void main(String[] args) {

   ArrayList<Cat> cats = new ArrayList<>();
   Cat thomas = new Cat("Thomas");
   Cat behemoth = new Cat("Behemoth");
   Cat lionel = new Cat("Lionel Messi");
   Cat fluffy = new Cat ("Fluffy");

   cats.add(thomas);
   cats.add(behemoth);
   cats.add(lionel);
   cats.add(fluffy);

   for (Cat cat: cats) {

       if (cat.name.equals("Behemoth")) {
           cats.remove(cat);
       }
   }

   System.out.println(cats);
}
Koden ser helt logisk ut. Men resultatet kan være en stor overraskelse: Unntak i tråden "main" java.util.ConcurrentModificationException på java.util.ArrayList$Itr.checkForComodification(ArrayList.java:859) på java.util.ArrayList$Itr.next(ArrayList. java:831) på Cat.main(Cat.java:25) Det er en slags feil, og det er uklart hvorfor den oppstod. Denne prosessen innebærer en rekke nyanser som må tas opp. Her er den generelle regelen du må huske: Du kan ikke samtidig iterere over en samling og endre dens elementer. Og vi mener enhver form for endring, ikke bare fjerning. Hvis du erstatter kattefjerningen med et forsøk på å sette inn nye katter, vil resultatet være det samme:
for (Cat cat: cats) {

   cats.add(new Cat("Salem Saberhagen"));
}

System.out.println(cats);
Unntak i tråden "main" java.util.ConcurrentModificationException på java.util.ArrayList$Itr.checkForComodification(ArrayList.java:859) på java.util.ArrayList$Itr.next(ArrayList.java:831) på Cat.main( Cat.java:25) Vi endret en operasjon til en annen, men resultatet endret seg ikke: vi får samme ConcurrentModificationException . Det oppstår nettopp når vi prøver å bryte regelen ovenfor ved å endre listen mens vi itererer over den. I Java trenger vi et spesielt objekt kalt en iterator (Iteratorklasse) for å slette elementer mens vi itererer over en samling. KlassenIteratorer ansvarlig for å trygt iterere over listen over elementer. Det er ganske enkelt, siden det bare har 3 metoder:
  • hasNext()- returnerer sant eller usant, avhengig av om det er et neste element i listen, eller om vi allerede har nådd det siste.
  • next()- returnerer neste element i listen
  • remove()- fjerner et element fra listen
Som du kan se, er iteratoren skreddersydd for våre behov, og samtidig er det ikke noe komplisert med det. Anta at vi vil sjekke om det er et neste element i listen vår, og vise det hvis det er:
Iterator<Cat> catIterator = cats.iterator();// Create an iterator
while(catIterator.hasNext()) {// As long as there are elements in the list

   Cat nextCat = catIterator.next();// Get the next element
   System.out.println(nextCat);// Display it
}
Utdata: Cat{name='Thomas'} Cat{name='Behemoth'} Cat{name='Lionel Messi'} Cat{name='Fluffy'} Som du kan se, har den allerede implementert en spesiell ArrayListmetode for å lage en iterator iterator():. Vær i tillegg oppmerksom på at når vi oppretter en iterator, spesifiserer vi klassen av objekter som den vil fungere med ( <Cat>). Poenget er at en iterator enkelt håndterer vår opprinnelige oppgave. Fjern for eksempel katten som heter "Lionel Messi":
Iterator<Cat> catIterator = cats.iterator();// Create an iterator
while(catIterator.hasNext()) {// As long as there are elements in the list

   Cat nextCat = catIterator.next();// Get the next element
   if (nextCat.name.equals("Lionel Messi")) {
       catIterator.remove();// Delete the cat with the specified name
   }
}

System.out.println(cats);
Utdata: [Cat{name='Thomas'}, Cat{name='Behemoth'}, Cat{name='Fluffy'}] Du har kanskje lagt merke til at vi ikke spesifiserte verken indeksen eller navnet i iteratorens remove()metode ! Iteratoren er smartere enn den kan se ut: remove()fjerner det siste elementet returnert av iteratoren. Som du kan se, gjorde den akkurat det vi ville at den skulle gjøre :) I prinsippet er dette alt du trenger å vite om å fjerne elementer fra en ArrayList. Vel, nesten alt. I neste leksjon skal vi se inne i denne timen, og se hva som skjer der under ulike metodekall :) Inntil da!
Kommentarer
  • Populær
  • Ny
  • Gammel
Du må være pålogget for å legge igjen en kommentar
Denne siden har ingen kommentarer ennå