JavaRush /Java Blog /Random-TL /Pag-alis ng isang elemento mula sa isang ArrayList sa Jav...

Pag-alis ng isang elemento mula sa isang ArrayList sa Java

Nai-publish sa grupo
Kamusta! Sa huling lecture, nakilala namin ang klase ng ArrayList , at natutunan din kung paano gawin ang mga pinakakaraniwang operasyon dito. Bilang karagdagan, natukoy namin ang ilang mga pagkakaiba sa pagitan ng ArrayList at isang regular na array. Ngayon tingnan natin ang pag-alis ng isang elemento mula sa ArrayList. Nasabi na namin na ang pagtanggal ng mga elemento sa isang regular na array ay hindi masyadong maginhawa. Pag-alis ng isang elemento mula sa isang ArrayList - 1Dahil hindi natin matatanggal ang cell mismo, maaari lang nating "zero" ang halaga nito:
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("Hippopotamus");
       cats[2] = new Cat("Philip Markovich");

       cats[1] = null;

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


@Override
   public String toString() {
       return "Cat{" +
               "name='" + name + '\'' +
               '}';
   }
}
Konklusyon:

[Cat{name='Томас'}, null, Cat{name='Фorпп Маркович'}]
Ngunit kapag na-reset, isang "butas" ang nananatili sa array. Hindi namin tinatanggal ang cell, ngunit ang mga nilalaman lamang nito. Isipin kung ano ang mangyayari kung mayroon kaming isang hanay ng 50 pusa, 17 sa mga ito ay tinanggal namin sa ganitong paraan. Magkakaroon tayo ng array na may 17 butas, at alagaan sila! Ang pag-alala nang buong puso sa mga bilang ng mga walang laman na cell kung saan maaari kang magsulat ng mga bagong halaga ay hindi makatotohanan. Magkamali ng isang beses at ipapatungan mo ang cell gamit ang nais na reference sa bagay. Mayroong, siyempre, isang pagkakataon na gawin ito nang mas maingat: pagkatapos ng pagtanggal, ilipat ang mga elemento ng array sa simula, upang ang "butas" ay nasa dulo:
public static void main(String[] args) {

   Cat[] cats = new Cat[4];
   cats[0] = new Cat("Thomas");
   cats[1] = new Cat("Hippopotamus");
   cats[2] = new Cat("Philip Markovich");
   cats[3] = new Cat("Fluff");

   cats[1] = null;

   for (int i = 2; i < cats.length-1; i++) {
       //move the elements to the beginning so that the empty cell is at the end
       cats[i-1] = cats[i];
       cats[i] = null;
   }

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

[Cat{name='Томас'}, Cat{name='Фorпп Маркович'}, Cat{name='Пушок'}, null]
Ngayon ay mukhang mas mahusay, ngunit ito ay halos hindi matatawag na isang matatag na solusyon. Sa pinakamababa, dahil kailangan nating isulat ang code na ito sa pamamagitan ng kamay sa tuwing aalisin natin ang isang elemento mula sa array! Masamang opsyon. Maaari kang pumunta sa ibang paraan at lumikha ng isang hiwalay na paraan:
public void deleteCat(Cat[] cats, int indexToDelete) {
   //...remove the cat by index and shift the elements
}
Ngunit ito ay hindi gaanong kapaki-pakinabang: ang pamamaraang ito ay maaari lamang gumana sa mga bagay Cat, ngunit hindi maaaring gumana sa iba. Iyon ay, kung mayroong 100 higit pang mga klase sa programa kung saan gusto nating gumamit ng mga array, kakailanganin nating isulat ang parehong pamamaraan na may eksaktong parehong lohika sa bawat isa sa kanila. Ito ay isang kumpletong kabiguan -_- Ngunit sa klase ng ArrayList ang problemang ito ay matagumpay na nalutas! Nagpapatupad ito ng isang espesyal na paraan para sa pag-alis ng mga elemento - remove():
public static void main(String[] args) {

   ArrayList<Cat> cats = new ArrayList<>();
   Cat thomas = new Cat("Thomas");
   Cat behemoth = new Cat("Hippopotamus");
   Cat philipp = new Cat("Philip Markovich");
   Cat pushok = new Cat("Fluff");

   cats.add(thomas);
   cats.add(behemoth);
   cats.add(philipp);
   cats.add(pushok);
   System.out.println(cats.toString());

   cats.remove(1);

   System.out.println(cats.toString());
}
Ipinasa namin ang index ng aming bagay sa pamamaraan, at ito ay tinanggal (tulad ng sa isang array). Ang pamamaraan remove()ay may dalawang tampok. Una , hindi ito nag-iiwan ng "mga butas". Ipinapatupad na nito ang lohika ng paglilipat ng mga elemento kapag nag-aalis ng elemento mula sa gitna, na dati naming isinulat sa pamamagitan ng kamay. Tingnan ang output ng nakaraang code sa console:

[Cat{name='Томас'}, Cat{name='Бегемот'}, Cat{name='Фorпп Маркович'}, Cat{name='Пушок'}]
[Cat{name='Томас'}, Cat{name='Фorпп Маркович'}, Cat{name='Пушок'}]
Inalis namin ang isang pusa sa gitna at ang iba ay inilipat sa paligid upang walang mga puwang. Pangalawa , maaari itong magtanggal ng isang bagay hindi lamang sa pamamagitan ng index (tulad ng isang regular na array), kundi pati na rin sa pamamagitan ng pagtukoy sa bagay :
public static void main(String[] args) {

   ArrayList<Cat> cats = new ArrayList<>();
   Cat thomas = new Cat("Thomas");
   Cat behemoth = new Cat("Hippopotamus");
   Cat philipp = new Cat("Philip Markovich");
   Cat pushok = new Cat("Fluff");

   cats.add(thomas);
   cats.add(behemoth);
   cats.add(philipp);
   cats.add(pushok);
   System.out.println(cats.toString());

   cats.remove(philipp);

   System.out.println(cats.toString());
}
Konklusyon:

[Cat{name='Томас'}, Cat{name='Бегемот'}, Cat{name='Фorпп Маркович'}, Cat{name='Пушок'}]
[Cat{name='Томас'}, Cat{name='Бегемот'}, Cat{name='Пушок'}]
Ito ay maaaring maging napaka-maginhawa kung hindi mo nais na palaging panatilihin ang index ng nais na bagay sa iyong ulo. Mukhang inayos namin ang karaniwang pagtanggal. Ngayon isipin natin ang sitwasyong ito: gusto nating ulitin ang listahan ng mga elemento at alisin ang isang pusa na may partikular na pangalan. Para dito gumagamit kami ng isang espesyal na operator ng loop for- for each. Maaari kang matuto nang higit pa tungkol dito sa panayam na ito .
public static void main(String[] args) {

   ArrayList<Cat> cats = new ArrayList<>();
   Cat thomas = new Cat("Thomas");
   Cat behemoth = new Cat("Hippopotamus");
   Cat philipp = new Cat("Philip Markovich");
   Cat pushok = new Cat("Fluff");

   cats.add(thomas);
   cats.add(behemoth);
   cats.add(philipp);
   cats.add(pushok);

   for (Cat cat: cats) {

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

   System.out.println(cats);
}
Ang code ay mukhang medyo lohikal. Gayunpaman, ang resulta ay maaaring mabigla sa iyo:

Exception in thread "main" java.util.ConcurrentModificationException
  at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:859)
  at java.util.ArrayList$Itr.next(ArrayList.java:831)
  at Cat.main(Cat.java:25)
Isang uri ng pagkakamali, at hindi malinaw kung bakit ito biglang lumitaw. Mayroong isang bilang ng mga nuances sa prosesong ito na kailangang harapin. Isang pangkalahatang tuntunin na kailangan mong tandaan: Hindi ka maaaring umulit sa isang koleksyon at baguhin ang mga elemento nito nang sabay. Oo, oo, eksaktong pagbabago, at hindi lamang isang pagtanggal. Kung susubukan mo sa aming code na palitan ang pag-alis ng mga pusa ng pagpasok ng mga bago, ang resulta ay pareho:
for (Cat cat: cats) {

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

System.out.println(cats);

Exception in thread "main" java.util.ConcurrentModificationException
  at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:859)
  at java.util.ArrayList$Itr.next(ArrayList.java:831)
  at Cat.main(Cat.java:25)
Binago namin ang isang operasyon sa isa pa, ngunit hindi nagbago ang resulta: ang parehong error ConcurrentModificationException. Nangyayari ito nang eksakto kapag sinubukan naming labagin ang isang panuntunan at baguhin ang listahan habang inuulit ito. Sa Java, upang alisin ang mga elemento sa panahon ng pag-ulit, kailangan mong gumamit ng isang espesyal na bagay - isang iterator (class Iterator). Ang klase Iteratoray responsable para sa ligtas na paglalakad sa isang listahan ng mga elemento. Ito ay medyo simple dahil mayroon lamang itong 3 mga pamamaraan:
  • hasNext()- bumabalik truedepende falsesa kung may susunod na elemento sa listahan, o kung naabot na natin ang huli.
  • next()- ibinabalik ang susunod na elemento ng listahan
  • remove()- nag-aalis ng elemento sa listahan
Tulad ng nakikita mo, ang iterator ay literal na "iniayon" sa aming mga pangangailangan, at walang kumplikado tungkol dito. Halimbawa, gusto naming suriin kung ang aming listahan ay naglalaman ng sumusunod na elemento, at kung gayon, i-print ito sa console:
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 next element
   System.out.println(nextCat);// print it to the console
}
Konklusyon:

Cat{name='Томас'}
Cat{name='Бегемот'}
Cat{name='Фorпп Маркович'}
Cat{name='Пушок'}
Tulad ng nakikita mo, ang klase ArrayListay nagpapatupad na ng isang espesyal na pamamaraan para sa paglikha ng isang iterator - iterator(). Gayundin, tandaan na kapag lumilikha ng isang iterator, tinutukoy namin ang klase ng mga bagay kung saan ito gagana ( <Cat>). Sa huli, madali naming malulutas ang aming orihinal na problema gamit ang isang iterator. Halimbawa, tanggalin natin ang isang pusa na pinangalanang "Philip Markovich":
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 next element
   if (nextCat.name.equals("Philip Markovich")) {
       catIterator.remove();//delete the cat with the desired name
   }
}

System.out.println(cats);
Konklusyon:

[Cat{name='Томас'}, Cat{name='Бегемот'}, Cat{name='Пушок'}]
Maaaring napansin mo na hindi namin tinukoy ang alinman sa index ng elemento o ang reference na pangalan ng variable sa pamamaraan ng iterator remove()! Ang iterator ay mas matalino kaysa sa tila: ang pamamaraan remove()ay nag-aalis ng huling elemento na ibinalik ng iterator. Tulad ng nakikita mo, gumana ito nang eksakto kung kinakailangan :) Iyan ang karaniwang lahat ng kailangan mong malaman tungkol sa pag-alis ng mga elemento mula sa ArrayList. Mas tiyak - halos lahat. Sa susunod na lektura titingnan natin ang "loob" ng klase na ito at tingnan kung ano ang nangyayari doon sa panahon ng operasyon :) See you!
Mga komento
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION