Hi! Sa huling aralin, nakilala namin ang
ArrayList
klase, at natutunan kung paano gawin ang pinakakaraniwang mga operasyon sa klase na ito. Bilang karagdagan, itinuro namin ang ilang mga pagkakaiba sa pagitan ng isang ArrayList
at isang ordinaryong array. Ngunit nilampasan namin ang isang paksa, ibig sabihin, kung paano magtanggal ng mga elemento mula sa isang ArrayList
. Pag-uusapan natin yan ngayon. Nabanggit na namin na ang pagtanggal ng mga elemento mula sa isang ordinaryong array ay hindi masyadong maginhawa. Dahil hindi natin matanggal ang mismong elemento, maaari lang nating "zero out" (itakda sa null) 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("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'}] Ngunit ang pagtatakda ng array element sa null ay nag-iiwan ng "butas". Hindi namin inalis ang posisyon sa array, tanging ang mga nilalaman nito. Isipin kung ano ang mangyayari kung mayroon kaming isang hanay ng 50 pusa at inalis ang 17 sa kanila sa ganitong paraan. Magkakaroon tayo ng array na may 17 butas. Subukan lamang na subaybayan ang mga ito! Hindi makatotohanang asahan na matandaan ang bilang ng mga walang laman na cell kung saan maaari kang magsulat ng mga bagong value. Kung magkamali ka, o-overwrite mo ang isang object reference na gusto mo. Mayroong, siyempre, isang paraan upang gawin ito nang mas maingat: pagkatapos alisin ang isang elemento, ilipat ang mga elemento sa harap ng array upang ilagay ang "butas" sa dulo:
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] Mukhang mas maganda ito, ngunit hindi ito matatawag na matatag na solusyon. Kung walang ibang dahilan kundi ang katotohanang kailangan nating isulat ang code na ito sa bawat oras na tatanggalin natin ang isang elemento mula sa isang array! Ito ay isang masamang opsyon. Maaari tayong pumunta sa ibang paraan at lumikha ng isang hiwalay na paraan:
public void deleteCat(Cat[] cats, int indexToDelete) {
//...delete the cat corresponding to the index and move the elements
}
Ngunit ito ay hindi gaanong kapaki-pakinabang: ang pamamaraang ito ay maaari lamang gumana sa Cat
mga bagay, ngunit hindi sa iba pang mga uri. Sa madaling salita, kung ang isang programa ay may isa pang 100 klase na gusto naming gamitin sa mga array, kakailanganin naming isulat ang parehong paraan na may eksaktong parehong lohika sa bawat isa sa kanila. Ito ay isang kabuuang sakuna -_- Ngunit ArrayList
nalutas ng klase ang problemang ito! 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("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());
}
Ipinapasa namin ang index ng aming object sa pamamaraan, na nagtatanggal nito (tulad ng sa isang array). Ang remove()
pamamaraan ay may dalawang espesyal na tampok. Una, hindi ito nag-iiwan ng "mga butas". Ipinapatupad na nito ang lohika na kailangan upang ilipat ang mga elemento kapag ang isang elemento ay tinanggal mula sa gitna, na dati nating isinulat mismo. Tingnan ang output mula sa nakaraang code:
[Cat{name='Thomas'}, Cat{name='Behemoth'}, Cat{name='Lionel Messi'}, Cat{name='Fluffy'}]
[Cat{name='Thomas'}, Cat{name='Lionel Messi'}, Cat{name='Fluffy'}]
Inalis namin ang isang pusa mula sa gitna, at ang iba ay inilipat upang walang walang laman na mga puwang. Pangalawa , maaari itong magtanggal ng mga bagay hindi lamang sa pamamagitan ng index (tulad ng isang normal na hanay), ngunit din sa pamamagitan ng sanggunian :
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'}, Pusa{name='Behemoth'}, Pusa{name='Fluffy'}] Ito ay maaaring maging napaka-maginhawa kung hindi mo gustong palaging subaybayan ang index ng gustong bagay. Mukhang naisip namin ang ordinaryong pagtanggal. Ngayon isipin natin ang sitwasyong ito: gusto naming ulitin ang aming listahan at alisin ang isang pusa na may partikular na pangalan . Para magawa ito, gagamit kami ng fast for
loop (tinatawag ding for-each loop), na ipinakilala sa amin sa mga aralin ni Rishi:
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);
}
Ang code ay mukhang ganap na lohikal. Ngunit ang resulta ay maaaring isang malaking sorpresa: Exception sa thread na "pangunahing" java.util.ConcurrentModificationException sa java.util.ArrayList$Itr.checkForComodification(ArrayList.java:859) sa java.util.ArrayList$Itr.next(ArrayList. java:831) sa Cat.main(Cat.java:25) Mayroong ilang uri ng error, at hindi malinaw kung bakit ito nangyari. Ang prosesong ito ay nagsasangkot ng isang bilang ng mga nuances na dapat matugunan. Narito ang pangkalahatang tuntunin na kailangan mong tandaan: Hindi mo maaaring sabay na umulit sa isang koleksyon at baguhin ang mga elemento nito. At ang ibig naming sabihin ay anumang uri ng pagbabago, hindi lamang pagtanggal. Kung papalitan mo ang pag-alis ng pusa ng pagtatangkang magpasok ng mga bagong pusa, magiging pareho ang resulta:
for (Cat cat: cats) {
cats.add(new Cat("Salem Saberhagen"));
}
System.out.println(cats);
Exception sa thread na "main" java.util.ConcurrentModificationException sa java.util.ArrayList$Itr.checkForComodification(ArrayList.java:859) sa java.util.ArrayList$Itr.next(ArrayList.java:831) sa Cat.main( Cat.java:25) Binago namin ang isang operasyon sa isa pa, ngunit hindi nagbago ang resulta: nakuha namin ang parehong ConcurrentModificationException . Nangyayari ito nang eksakto kapag sinubukan naming labagin ang panuntunan sa itaas sa pamamagitan ng pagpapalit ng listahan habang inuulit ito. Sa Java, kailangan namin ng isang espesyal na bagay na tinatawag na isang iterator (Iterator
klase) upang tanggalin ang mga item habang umuulit sa isang koleksyon. AngIterator
klase ay responsable para sa ligtas na pag-ulit sa listahan ng mga elemento. Ito ay medyo simple, dahil mayroon lamang itong 3 mga pamamaraan:
hasNext()
- nagbabalik ng totoo o mali, depende sa kung may susunod na item sa listahan, o naabot na natin ang huli.next()
- ibinabalik ang susunod na item sa listahanremove()
- nag-aalis ng isang item mula sa listahan
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: Pusa{name='Thomas'} Pusa{name='Behemoth'} Pusa{name='Lionel Messi'} Pusa{name='Fluffy'} Gaya ng nakikita mo, nagpatupad na ang isang ArrayList
espesyal na paraan para sa paglikha ng isang iterator: iterator()
. Bilang karagdagan, tandaan na kapag lumikha kami ng isang iterator, tinukoy namin ang klase ng mga bagay na gagana sa ( <Cat>
). Ang ilalim na linya ay ang isang iterator ay madaling pinangangasiwaan ang aming orihinal na gawain. Halimbawa, alisin ang pusang pinangalanang "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'}] Maaaring napansin mo na hindi namin tinukoy ang alinman sa index o ang pangalan sa remove()
pamamaraan ng iterator ! Ang iterator ay mas matalino kaysa sa maaaring lumitaw: remove()
inaalis ang huling elemento na ibinalik ng iterator. Tulad ng nakikita mo, ginawa nito ang gusto naming gawin :) Sa prinsipyo, ito ang lahat ng kailangan mong malaman tungkol sa pag-alis ng mga elemento mula sa isang ArrayList
. Well, halos lahat. Sa susunod na aralin, titingnan natin ang loob ng klaseng ito, at tingnan kung ano ang mangyayari doon sa iba't ibang method call :) Hanggang doon na lang!
GO TO FULL VERSION