สวัสดี! ในบทเรียนก่อนหน้านี้ เราได้เจาะลึกเกี่ยวกับอาร์เรย์และทบทวนตัวอย่างทั่วไปของการทำงานกับอาร์เรย์ ในบทเรียนนี้ เราจะตรวจสอบ Java ArrayList ให้ละเอียดยิ่งขึ้น โดยทั่วไป อาร์เรย์มีประโยชน์มาก และอย่างที่คุณสังเกตเห็นแล้ว คุณสามารถทำอะไรกับมันได้มากมาย :) แต่อาร์เรย์ก็มีข้อบกพร่องอยู่หลายประการ
- ขนาดจำกัด. คุณจำเป็นต้องรู้ว่าอาร์เรย์ของคุณต้องมีองค์ประกอบกี่รายการในเวลาที่คุณสร้าง หากคุณประมาท คุณจะมีพื้นที่ไม่เพียงพอ ประเมินค่าสูงเกินไป และอาร์เรย์จะยังคงว่างเปล่าอยู่ครึ่งหนึ่ง ซึ่งก็ไม่ดีเช่นกัน ท้ายที่สุด คุณยังคงจัดสรรหน่วยความจำมากเกินความจำเป็น
- อาร์เรย์ไม่มีวิธีการเพิ่มองค์ประกอบ คุณต้องระบุดัชนีของตำแหน่งที่คุณต้องการเพิ่มองค์ประกอบอย่างชัดเจนเสมอ หากคุณระบุดัชนีสำหรับตำแหน่งที่ต้องการโดยไม่ได้ตั้งใจ ค่านั้นจะถูกเขียนทับ
- ไม่มีวิธีการลบรายการ ค่าสามารถเป็น "ศูนย์ออก" เท่านั้น
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 + '\'' +
'}';
}
}
ผลลัพธ์: [Cat{name='Thomas'}, null, Cat{name='Lionel Messi'}] โชคดีที่ผู้สร้าง Java ทราบดีถึงข้อดีและข้อเสียของอาร์เรย์ ดังนั้นจึงสร้างโครงสร้างข้อมูลที่น่าสนใจมากชื่อJava ArrayList พูดให้ง่ายที่สุดเท่าที่จะเป็นไปได้Java ArrayListเป็นอาร์เรย์ที่ "เติมเต็ม" พร้อมคุณสมบัติใหม่มากมาย
วิธีสร้าง ArrayList
มันง่ายมากที่จะสร้าง:
ArrayList<Cat> cats = new ArrayList<Cat>();
ตอนนี้เราได้สร้างรายการสำหรับจัดเก็บวัตถุCat โปรดทราบว่าเราไม่ได้ระบุขนาดของArrayListเนื่องจากสามารถขยายได้โดยอัตโนมัติ เป็นไปได้อย่างไร? มันค่อนข้างง่ายจริงๆ อาจทำให้คุณประหลาดใจ แต่ArrayList ใน Javaสร้างขึ้นจากอาร์เรย์ธรรมดาๆ :) ใช่ มันมีอาร์เรย์ และนั่นคือที่เก็บองค์ประกอบของเรา แต่ArrayListใน Java มีวิธีพิเศษในการทำงานกับอาร์เรย์นั้น:
- เมื่อเติมอาร์เรย์ภายในแล้ว ArrayList จะสร้างอาร์เรย์ใหม่ภายใน ขนาดของอาร์เรย์ใหม่คือขนาดของอาร์เรย์เก่าคูณ 1.5 บวก 1
- ข้อมูลทั้งหมดจะถูกคัดลอกจากอาร์เรย์เก่าไปยังอาร์เรย์ใหม่
- อาร์เรย์เก่าถูกล้างโดยตัวเก็บขยะ
add()
วิธีการ
public static void main(String[] args) {
ArrayList<Cat> cats = new ArrayList<Cat>();
cats.add(new Cat("Behemoth"));
}
รายการใหม่จะถูกเพิ่มที่ส่วนท้ายของรายการ ตอนนี้ไม่มีความเสี่ยงที่จะล้นอาร์เรย์ ดังนั้นวิธีนี้จึงปลอดภัยอย่างสมบูรณ์ อย่างไรก็ตามArrayListไม่เพียงแต่สามารถค้นหาวัตถุด้วยดัชนีของมันเท่านั้น แต่ยังในทางกลับกันอีกด้วย: มันสามารถใช้การอ้างอิงเพื่อค้นหาดัชนีของวัตถุในArrayList ! นี่คือสิ่งที่ เมธอด indexOf()มีไว้สำหรับ: เราส่งการอ้างอิงไปยังวัตถุที่เราต้องการ และindexOf()ส่งกลับดัชนีของมัน:
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);
int thomasIndex = cats.indexOf(thomas);
System.out.println(thomasIndex);
}
ผลลัพธ์: 0 ถูกต้อง วัตถุ โทมัสของเราถูกเก็บไว้ในองค์ประกอบ 0 อาร์เรย์ไม่ได้มีเพียงข้อเสียเท่านั้น พวกเขายังมีข้อได้เปรียบที่ไม่อาจปฏิเสธได้ หนึ่งในนั้นคือความสามารถในการค้นหาองค์ประกอบตามดัชนี เนื่องจากเราชี้ไปที่ดัชนี เช่น ไปยังที่อยู่หน่วยความจำเฉพาะ การค้นหาอาร์เรย์ด้วยวิธีนี้จึงรวดเร็วมาก ArrayList
รู้วิธีทำด้วย! เมธอดget()ใช้สิ่งนี้:
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);
Cat secondCat = cats.get(1);
System.out.println(secondCat);
}
ผลลัพธ์: Cat{name='Behemoth'} นอกจากนี้ คุณสามารถค้นหาได้อย่างง่ายดายว่าArrayListมีวัตถุใดวัตถุหนึ่งหรือไม่ ซึ่งทำได้โดยใช้ เมธอด ArrayListมี ():
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);
cats.remove(fluffy);
System.out.println(cats.contains(fluffy));
}
วิธีการตรวจสอบว่า อาร์เรย์ภายในของ ArrayListมีองค์ประกอบหรือไม่ และส่งกลับค่าบูลีน (จริงหรือเท็จ) ผลลัพธ์: เท็จ และสิ่งสำคัญอีกอย่างเกี่ยวกับการแทรก ArrayListให้คุณใช้ดัชนีเพื่อแทรกองค์ประกอบต่างๆ ไม่เพียงแต่ที่ส่วนท้ายของอาร์เรย์เท่านั้น แต่ที่ใดก็ได้ มีสองวิธีสำหรับสิ่งนี้:
- เพิ่ม ArrayList (ดัชนี int, องค์ประกอบ Cat)
- ชุด ArrayList (ดัชนี int, องค์ประกอบ Cat)
นี่คือตัวอย่าง:
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);
System.out.println(cats.toString());
cats.set(0, lionel);// Now we have a list of 2 cats. Adding a 3rd using set
System.out.println(cats.toString());
}
ผลลัพธ์: [[Cat{name='Thomas'}, Cat{name='Behemoth'}] [Cat{name='Lionel Messi'}, Cat{name='Behemoth'}] เรามีรายชื่อแมว 2 ตัว จากนั้นเราแทรกอีกอันหนึ่งเป็นองค์ประกอบ 0 โดยใช้วิธีset() เป็นผลให้องค์ประกอบเก่าถูกแทนที่ด้วยองค์ประกอบใหม่
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);
System.out.println(cats.toString());
cats.add(0, lionel);// Now we have a list of 2 cats. Adding a 3rd using add
System.out.println(cats.toString());
}
และที่นี่เราเห็นว่าadd()ทำงานแตกต่างกัน โดยจะย้ายองค์ประกอบทั้งหมดไปทางขวา จากนั้นเขียนค่าใหม่เป็นองค์ประกอบ 0 ผลลัพธ์: [Cat{name='Thomas'}, Cat{name='Behemoth'}] [Cat{name='Lionel Messi'}, Cat{name='Thomas'}, Cat{name='Behemoth'}] ในการล้างรายการทั้งหมด เราใช้ เมธอด clear() :
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);
cats.clear();
System.out.println(cats.toString());
}
เอาต์พุต: [] ทุกอย่างถูกลบออกจากรายการ อย่างไรก็ตาม โปรดทราบว่าArrayListจะแทนที่เมธอดtoString()ซึ่งแตกต่างจากอาร์เรย์ และแสดงรายการเป็นสตริงอย่างเหมาะสมอยู่แล้ว ด้วยอาร์เรย์ธรรมดา เราต้องใช้ คลาส อาร์เรย์สำหรับสิ่งนี้ และตั้งแต่ฉันพูดถึงArrays : Java ให้คุณ "สลับ" ระหว่างอาร์เรย์และArrayList ได้อย่างง่ายดาย เช่น แปลงหนึ่งไปยังอีกอันหนึ่ง คลาสArraysมี เมธอด Arrays.asList()สำหรับสิ่งนี้ เราใช้มันเพื่อรับเนื้อหาเป็นอาร์เรย์และส่งต่อไปยัง ตัวสร้าง ArrayList ของเรา :
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");
Cat[] catsArray = {thomas, behemoth, lionel, fluffy};
ArrayList<Cat> catsList = new ArrayList<>(Arrays.asList(catsArray));
System.out.println(catsList);
}
ผลลัพธ์: [Cat{name='Thomas'}, Cat{name='Behemoth'}, Cat{name='Lionel Messi'}, Cat{name='Fluffy'}] คุณยังสามารถไปในทิศทางตรงกันข้าม: รับ อาร์เรย์จากวัตถุArrayList เราทำสิ่งนี้โดยใช้ เมธอด toArray() :
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);
Cat[] catsArray = cats.toArray(new Cat[0]);
System.out.println(Arrays.toString(catsArray));
}
หมายเหตุ: เราส่งอาร์เรย์ว่างไปยังเมธอดtoArray() นี่ไม่ใช่ข้อผิดพลาด ภายใน คลาส ArrayListวิธีการนี้ถูกนำมาใช้ในลักษณะที่ส่งผ่านอาร์เรย์ที่ว่างเปล่าเพื่อเพิ่มประสิทธิภาพ เพียงจำสิ่งนี้ไว้สำหรับอนาคต (แน่นอน คุณสามารถส่งอาร์เรย์ที่มีขนาดเฉพาะเจาะจงได้ ซึ่งจะได้ผลเช่นกัน) โอ้เกี่ยวกับขนาด ขนาดปัจจุบันของรายการสามารถพบได้โดยใช้ เมธอด size() :
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.size());
}
สิ่งสำคัญคือต้องเข้าใจว่าไม่เหมือนกับคุณสมบัติความยาว ของอาร์เรย์ เมธอด ArrayList.size()จะส่งคืนจำนวนองค์ประกอบจริง ไม่ใช่ความจุดั้งเดิม เพราะเราไม่ได้ระบุขนาดเมื่อสร้างArrayList อย่างไรก็ตาม คุณสามารถระบุได้ — ArrayListมีตัวสร้างที่เหมาะสม แต่ในแง่ของการเพิ่มองค์ประกอบใหม่ สิ่งนี้ไม่ได้เปลี่ยนพฤติกรรม:
public static void main(String[] args) {
ArrayList<Cat> cats = new ArrayList<>(2);// create an ArrayList with an initial capacity of 2
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.size());
}
เอาต์พุตของคอนโซล: 4 เราได้สร้างรายการขององค์ประกอบ 2 รายการ แต่มันขยายอย่างเงียบๆ เมื่อเราต้องการ ข้อพิจารณาอีกประการหนึ่งคือหากเราสร้างรายการขนาดเล็กมากในขั้นต้น จะต้องขยายบ่อยขึ้นซึ่งจะใช้ทรัพยากรบางส่วน เราแทบไม่ได้แตะต้องกระบวนการลบองค์ประกอบออกจากArrayListในบทเรียนนี้ แน่นอนว่านี่ไม่ใช่เพราะมันหลุดจากความคิดของเรา เราได้แยกหัวข้อนี้ออกเป็นบทเรียนแยกต่างหากซึ่งคุณจะพบในภายหลัง :) เพื่อเสริมสิ่งที่คุณได้เรียนรู้ เราขอแนะนำให้คุณดูบทเรียนวิดีโอจากหลักสูตร Java ของเรา
GO TO FULL VERSION