John Squirrels
ระดับ
San Francisco

Java ArrayList

เผยแพร่ในกลุ่ม
สวัสดี! ในบทเรียนก่อนหน้านี้ เราได้เจาะลึกเกี่ยวกับอาร์เรย์และทบทวนตัวอย่างทั่วไปของการทำงานกับอาร์เรย์ ในบทเรียนนี้ เราจะตรวจสอบ 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

  • ข้อมูลทั้งหมดจะถูกคัดลอกจากอาร์เรย์เก่าไปยังอาร์เรย์ใหม่

  • อาร์เรย์เก่าถูกล้างโดยตัวเก็บขยะ
กลไกนี้ทำให้Java ArrayList (ไม่เหมือนกับอาร์เรย์ทั่วไป) ใช้วิธีเพิ่มองค์ประกอบใหม่ มันเป็น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)
เป็นอาร์กิวเมนต์ ทั้งสองวิธีนี้ใช้ดัชนีของตำแหน่งที่คุณต้องการแทรกและการอ้างอิงไปยังวัตถุ ความแตกต่างคือการแทรกโดยใช้set()เขียนทับค่าเก่า การแทรกโดยใช้add()อันดับแรกจะเลื่อนองค์ประกอบทั้งหมดจาก [index] ไปยังจุดสิ้นสุดของอาร์เรย์ แล้วจึงเพิ่มวัตถุที่ระบุในตำแหน่งว่างที่เป็นผลลัพธ์

นี่คือตัวอย่าง:


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 ของเรา
ความคิดเห็น
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION