CodeGym/Java blog/Tilfældig/Sletning af et element fra en ArrayList
John Squirrels
Niveau
San Francisco

Sletning af et element fra en ArrayList

Udgivet i gruppen
Hej! I den sidste lektion stiftede vi bekendtskab med klassen ArrayList, og lærte at udføre de mest almindelige operationer med denne klasse. Derudover påpegede vi flere forskelle mellem et ArrayListog et almindeligt array. Men vi overskred et emne, nemlig hvordan man sletter elementer fra en ArrayList. Det vil vi diskutere nu. Sletning af et element fra en ArrayList - 1Vi har allerede nævnt, at det ikke er særlig bekvemt at slette elementer fra et almindeligt array. Da vi ikke kan slette selve elementet, kan vi kun "nulstille" (sat til null) dets værdi:
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 + '\'' +
               '}';
   }
}
Output: [Cat{name='Thomas'}, null, Cat{name='Lionel Messi'}] Men at sætte et array-element til null efterlader et "hul". Vi har ikke fjernet positionen i arrayet, kun dens indhold. Forestil dig, hvad der ville ske, hvis vi havde en række af 50 katte og fjernede 17 af dem på denne måde. Vi får et array med 17 huller. Prøv bare at holde styr på dem! Det er urealistisk at forvente at huske antallet af tomme celler, hvor du kan skrive nye værdier. Hvis du laver en fejl, vil du overskrive en objektreference, du ønsker. Der er selvfølgelig en måde at gøre dette lidt mere omhyggeligt på: efter at have fjernet et element, skal du flytte elementerne til forsiden af ​​arrayet for at sætte "hullet" i enden:
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));
}
Output: [Cat{name='Thomas'}, Cat{name='Fluffy'}, Cat{name='Fluffy'}, null] Dette virker bedre, men det kan næppe kaldes en robust løsning. Om ikke andet for det faktum, at vi skal skrive denne kode hver gang, når vi sletter et element fra et array! Dette er en dårlig mulighed. Vi kunne gå en anden vej og skabe en separat metode:
public void deleteCat(Cat[] cats, int indexToDelete) {
   //...delete the cat corresponding to the index and move the elements
}
Men dette er også af ringe nytte: denne metode kan kun arbejde med Catobjekter, men ikke andre typer. Med andre ord, hvis et program har yderligere 100 klasser, som vi vil bruge med arrays, bliver vi nødt til at skrive den samme metode med nøjagtig den samme logik i hver af dem. Dette er en total katastrofe -_- Men ArrayListklassen løser dette problem! Den implementerer en speciel metode til at 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 vores objekts indeks til metoden, som sletter det (ligesom i et array). Metoden remove()har to særlige kendetegn. For det første efterlader den ikke "huller". Den implementerer allerede den logik, der er nødvendig for at flytte elementer, når et element fjernes fra midten, som vi tidligere selv skrev. Se på outputtet fra den 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 fjernede en kat fra midten, og resten blev flyttet, så der ikke var tomme pladser. For det andet kan den slette objekter ikke kun efter indeks (som en normal matrix), men også ved reference :
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());
}
Output: [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 meget praktisk, hvis du ikke altid vil holde styr på det ønskede objekts indeks. Det ser ud til, at vi har fundet ud af almindelig sletning. Lad os nu forestille os denne situation: vi ønsker at gentage vores liste og fjerne en kat med et specifikt navn . For at gøre dette bruger vi en hurtig forloop (også kaldet en for-each loop), som vi blev introduceret til i Rishis lektioner:
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 ud. Men resultatet kan være en stor overraskelse: Undtagelse 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) Der er en slags fejl, og det er uklart, hvorfor det opstod. Denne proces involverer en række nuancer, der skal behandles. Her er den generelle regel, du skal huske: Du kan ikke samtidig iterere over en samling og ændre dens elementer. Og vi mener enhver form for ændring, ikke blot fjernelse. Hvis du erstatter kattefjernelsen med et forsøg på at indsætte nye katte, vil resultatet være det samme:
for (Cat cat: cats) {

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

System.out.println(cats);
Undtagelse 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 ændrede en operation til en anden, men resultatet ændrede sig ikke: vi får den samme ConcurrentModificationException . Det sker netop, når vi forsøger at bryde reglen ovenfor ved at ændre listen, mens vi gentager den. I Java har vi brug for et specielt objekt kaldet en iterator (Iteratorklasse) for at slette elementer, mens vi itererer over en samling. KlassenIteratorer ansvarlig for sikkert at gentage listen over elementer. Det er ret simpelt, da det kun har 3 metoder:
  • hasNext()- returnerer sand eller falsk, alt efter om der er et næste punkt på listen, eller om vi allerede er nået til det sidste.
  • next()- returnerer det næste element på listen
  • remove()- fjerner et element fra listen
Som du kan se, er iteratoren skræddersyet til vores behov, og samtidig er der ikke noget kompliceret ved det. Antag, at vi vil kontrollere, om der er et næste element på vores liste, og vise det, hvis der 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
}
Output: Cat{name='Thomas'} Cat{name='Behemoth'} Cat{name='Lionel Messi'} Cat{name='Fluffy'} Som du kan se, har den allerede implementeret en ArrayListspeciel metode til at skabe en iterator iterator():. Bemærk desuden, at når vi opretter en iterator, angiver vi den klasse af objekter, som den vil arbejde med ( <Cat>). Den nederste linje er, at en iterator nemt klarer vores oprindelige opgave. Fjern f.eks. katten ved navn "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);
Output: [Cat{name='Thomas'}, Cat{name='Behemoth'}, Cat{name='Fluffy'}] Du har muligvis bemærket, at vi ikke har angivet hverken indekset eller navnet i iteratorens remove()metode ! Iteratoren er smartere, end den kan se ud: remove()fjerner det sidste element returneret af iteratoren. Som du kan se, gjorde den lige, hvad vi ville have den til at gøre :) I princippet er dette alt hvad du behøver at vide om at fjerne elementer fra en ArrayList. Nå, næsten alt. I næste lektion kigger vi indenfor i denne klasse, og ser hvad der sker der under forskellige metodekald :) Indtil da!
Kommentarer
  • Populær
  • Ny
  • Gammel
Du skal være logget ind for at skrive en kommentar
Denne side har ingen kommentarer endnu