สวัสดี! ในการบรรยายครั้งก่อน เราได้ตรวจสอบรายละเอียดเช่นโครงสร้างข้อมูลเป็นอาร์เรย์ และดูตัวอย่างทั่วไปของการทำงานร่วมกับโครงสร้างเหล่านั้น แต่โครงสร้างข้อมูลนี้มีข้อเสียหลายประการ คำตอบสำหรับพวกเขาใน Java คือรูปลักษณ์ของ ArrayList เพื่อให้ง่ายที่สุดเท่าที่จะเป็นไปได้ ArrayList ใน Java นั้นเป็นอาร์เรย์ "อัปเกรด" พร้อมคุณสมบัติใหม่มากมาย
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("Hippopotamus");
cats[2] = new Cat("Philip Markovich");
cats[1] = null;
System.out.println(Arrays.toString(cats));
}
@Override
public String toString() {
return "Cat{" +
"name='" + name + '\'' +
'}';
}
}
บทสรุป:
[Cat{name='Томас'}, null, Cat{name='Фorпп Маркович'}]
ข้อบกพร่องทั้งหมดนี้สามารถกำจัดได้โดยใช้ ArrayList มันถูกสร้างขึ้นอย่างเรียบง่าย:
ArrayList<Cat> cats = new ArrayList<Cat>();
ตอนนี้เราได้สร้างรายการเพื่อจัดเก็บวัตถุCat
แล้ว ใส่ใจ:เราไม่ได้ระบุขนาดของ ArrayList เนื่องจากสามารถขยายได้โดยอัตโนมัติ สิ่งนี้เป็นไปได้อย่างไร? อย่างง่ายดาย. คุณจะต้องแปลกใจ แต่ ArrayList ใช้อาร์เรย์ธรรมดา :) ใช่แล้ว ข้างในนั้นมีอาร์เรย์ที่องค์ประกอบของเราถูกเก็บไว้ แต่ ArrayList มีกลไกพิเศษในการทำงานกับมัน:
- เมื่ออาร์เรย์ภายในนี้เต็ม ArrayList จะสร้างอาร์เรย์ใหม่ภายในตัวมันเอง ขนาดของมัน = (ขนาดของอาเรย์เก่า * 1.5) +1
- ข้อมูลทั้งหมดจะถูกคัดลอกจากอาเรย์เก่าไปยังอาเรย์ใหม่
- อาร์เรย์เก่าจะถูกลบออกโดยตัวรวบรวมขยะ
add()
การ
public static void main(String[] args) {
ArrayList<Cat> cats = new ArrayList<Cat>();
cats.add(new Cat("Hippopotamus"));
}
องค์ประกอบใหม่จะถูกเพิ่มไปที่ส่วนท้ายของรายการ ขณะนี้ไม่มีความเสี่ยงที่จะล้น ดังนั้นกลไกนี้จึงปลอดภัยอย่างสมบูรณ์ อย่างไรก็ตาม ArrayList ไม่เพียงแต่สามารถค้นหาวัตถุตามดัชนีเท่านั้น แต่ยังสามารถค้นหาดัชนีของวัตถุใน ArrayList ได้โดยการอ้างอิงถึงวัตถุนั้นด้วย! ในการดำเนินการนี้จะใช้วิธีindexOf()
: เราส่งลิงก์ไปยังวัตถุที่ต้องการและindexOf()
ส่งคืนดัชนีให้เรา:
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);
int thomasIndex = cats.indexOf(thomas);
System.out.println(thomasIndex);
}
บทสรุป:
0
ถูกต้องแล้ว วัตถุนั้นthomas
ถูกจัดเก็บไว้ในเซลล์0
จริงๆ อาร์เรย์ไม่เพียงแต่มีข้อเสียเท่านั้น แต่ยังมีข้อดีอย่างไม่ต้องสงสัยอีกด้วย หนึ่งในนั้นคือการค้นหาองค์ประกอบตามดัชนี เนื่องจากเราชี้ไปที่ดัชนี นั่นคือ ที่อยู่เฉพาะในหน่วยความจำ การค้นหาอาร์เรย์จึงรวดเร็วมาก ArrayList ใน Java ก็สามารถทำได้เช่นกัน! เมื่อต้องการทำเช่นนี้ จะใช้วิธีget()
:
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);
Cat secondCat = cats.get(1);
System.out.println(secondCat);
}
บทสรุป:
Cat{name='Бегемот'}
นอกจากนี้คุณยังสามารถค้นหาได้อย่างง่ายดายว่า ArrayList มีวัตถุใดวัตถุหนึ่งหรือไม่ ทำได้โดยใช้วิธีการcontains()
:
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);
cats.remove(pushok);
System.out.println(cats.contains(pushok));
}
วิธีการตรวจสอบว่าองค์ประกอบมีอยู่ในอาร์เรย์ภายในของ ArrayList หรือ ไม่ และส่งกลับผลลัพธ์ในรูปแบบboolean
- true
หรือ false
บทสรุป:
false
และสิ่งสำคัญอีกประการหนึ่งเกี่ยวกับการแทรก ArrayList ช่วยให้คุณสามารถแทรกข้อมูลไม่เพียงแต่ที่ส่วนท้ายของอาร์เรย์ แต่ยังลงในเซลล์ใดๆ ตามดัชนีด้วย มีสองวิธีสำหรับสิ่งนี้:
add(int index, Cat element)
set(int index, Cat element)
set()
จะเขียนทับค่าเก่าที่จัดเก็บไว้ในเซลล์ และการแทรกผ่านadd()
ขั้นแรกจะเลื่อนองค์ประกอบทั้งหมดโดยเริ่มจาก[index]
จุดสิ้นสุดของอาร์เรย์ และเพิ่มวัตถุที่คุณต้องการลงในเซลล์ว่างที่เป็นผลลัพธ์ นี่คือตัวอย่าง:
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);
System.out.println(cats.toString());
cats.set(0, philipp);//Now we have a list of 2 cats. We add the 3rd via set:
System.out.println(cats.toString());
}
บทสรุป:
[[Cat{name='Томас'}, Cat{name='Бегемот'}]
[Cat{name='Фorпп Маркович'}, Cat{name='Бегемот'}]
เรา มี รายชื่อแมว 2 ตัว เราแทรกอีกตัวหนึ่งผ่านวิธีการset()
เข้าไปในเซลล์ 0
เป็นผลให้ค่าเก่าที่จัดเก็บไว้ในเซลล์นี้ถูกแทนที่ด้วยค่าใหม่
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);
System.out.println(cats.toString());
cats.add(0, philipp);//Now we have a list of 2 cats. Add the 3rd via add
System.out.println(cats.toString());
}
แต่มันadd()
ทำงานแตกต่างออกไป เขาเลื่อนองค์ประกอบทั้งหมดไปทางขวาแล้วเขียนค่าใหม่ลงใน0
เซลล์ บทสรุป:
[Cat{name='Томас'}, Cat{name='Бегемот'}]
[Cat{name='Фorпп Маркович'}, Cat{name='Томас'}, Cat{name='Бегемот'}]
หากต้องการล้างรายการทั้งหมด ให้ใช้วิธีclear()
:
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);
cats.clear();
System.out.println(cats.toString());
}
บทสรุป:
[]
เนื้อหาทั้งหมดถูกลบออกจากรายการแล้ว อย่างไรก็ตาม โปรดทราบ: ไม่เหมือนอาร์เรย์ใน ArrayList เมธอด toString() จะถูกแทนที่และแสดงรายการในรูปแบบสตริงทันที ในกรณีของอาร์เรย์ เราต้องใช้คลาส Arrays สำหรับสิ่งนี้ และเนื่องจากเราจำ Arrays ได้: ใน Java คุณสามารถ "สลับ" ระหว่างอาร์เรย์และ ArrayList ได้อย่างง่ายดาย นั่นคือแปลงอาร์เรย์หนึ่งเป็นอีกอาร์เรย์หนึ่ง คลาส Arrays มีเมธอดสำหรับสิ่งนี้ Arrays.asList() ด้วยความช่วยเหลือนี้ เราจึงได้รับเนื้อหาของอาร์เรย์เป็นรายการและส่งผ่านไปยังตัวสร้าง ArrayList ของเรา:
public static void main(String[] args) {
Cat thomas = new Cat("Thomas");
Cat behemoth = new Cat("Hippopotamus");
Cat philipp = new Cat("Philip Markovich");
Cat pushok = new Cat("Fluff");
Cat[] catsArray = {thomas, behemoth, philipp, pushok};
ArrayList<Cat> catsList = new ArrayList<>(Arrays.asList(catsArray));
System.out.println(catsList);
}
บทสรุป:
[Cat{name='Томас'}, Cat{name='Бегемот'}, Cat{name='Фorпп Маркович'}, Cat{name='Пушок'}]
คุณสามารถทำสิ่งที่ตรงกันข้ามได้ - รับอาร์เรย์จากวัตถุ ArrayList เมื่อต้องการทำเช่นนี้ ให้ใช้เมธอด toArray():
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);
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("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.size());
}
สิ่งสำคัญคือต้องเข้าใจในที่นี้ว่าlength
เมธอด 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("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.size());
}
เอาต์พุตคอนโซล:
4
เราสร้างรายการที่มี 2 องค์ประกอบ แต่เมื่อเราต้องการมันก็ขยายออกได้อย่างง่ายดาย อีกประการหนึ่งคือหากเราสร้างรายการเล็กๆ ขึ้นมาในตอนแรก รายการนั้นจะต้องดำเนินการขยายบ่อยขึ้น และนี่จะใช้ทรัพยากรจำนวนหนึ่ง ในการบรรยายนี้ เราแทบไม่ได้พูดถึงกระบวนการลบองค์ประกอบออกจาก ArrayList แน่นอนว่านี่ไม่ได้เกิดจากการหลงลืม หัวข้อนี้ถูกแยกออกเป็นบรรยายแยกต่างหากซึ่งคุณสามารถอ่านเพิ่มเติมได้ :)
GO TO FULL VERSION