-
การ แปลงอาร์เรย์ให้เป็นArrayList
ในการแปลงอาร์เรย์เป็นArrayListนักพัฒนามักใช้วิธีนี้:
List<String> list = Arrays.asList(arr);
Arrays.asList()
จะส่งคืนวัตถุคลาสArrayList
ซึ่งเป็นคลาสคงที่ส่วนตัวภายใน(private static class)
ของคลาสArrays
และนี่ไม่ใช่คลาสคลาสjava.util.ArrayList.
มีjava.util.Arrays.ArrayList
วิธีset()
,get()
,contains()
แต่ไม่มีวิธีการใด ๆ สำหรับการเพิ่มองค์ประกอบ ขนาดของมันได้รับการแก้ไขแล้ว หากต้องการสร้างของจริงjava.util.ArrayList
ให้ทำดังนี้:ArrayList<String> arrayList = new ArrayList<String>(Arrays.asList(arr));
ตัวสร้างคลาส
java.util.ArrayList
สามารถใช้เป็นพารามิเตอร์อ็อบเจ็กต์ทั้งหมดที่ใช้อินเทอร์เฟซCollection
ซึ่งการใช้งานนั้นสืบทอดมาจากคลาสjava.util.Arrays.ArrayList
(คลาสสแตติกส่วนตัว ArrayList<E> ขยาย AbstractList<E> ใช้ RandomAccess, java.io.Serializable)
-
การตรวจสอบอาร์เรย์เพื่อหาค่าเฉพาะ
นักพัฒนามักจะทำสิ่งนี้:
Set<String> set = new HashSet<String>(Arrays.asList(arr)); return set.contains(targetValue);
รหัสใช้งานได้ แต่ไม่จำเป็นต้องแปลง
List
เป็นSet
. การแปลงเป็นSet
จะใช้เวลาเพิ่มเติม ที่จริงแล้วทุกอย่างนั้นง่าย:Arrays.asList(arr).contains(targetValue);
หรือ
for(String s: arr){ if(s.equals(targetValue)) return true; } return false;
วิธีแรกสั้นกว่ามาก
-
การลบองค์ประกอบออกจาก
List
ในลูปพิจารณารหัสต่อไปนี้ที่จะลบองค์ประกอบในวง:
ArrayList<String> list = new ArrayList<String>(Arrays.asList("a", "b", "c", "d")); for (int i = 0; i < list.size(); i++) { list.remove(i); } System.out.println(list);
บทสรุป:
[b, d]
นี่กลายเป็นความผิดพลาดร้ายแรง เมื่อองค์ประกอบถูกลบ ขนาด
List
จะลดลง และดัชนีองค์ประกอบจะเปลี่ยนไปดังนั้นให้หลีกเลี่ยงวิธีนี้หากคุณต้องการลบหลายองค์ประกอบในลูปโดยใช้ดัชนี
คุณอาจรู้ว่าการใช้ตัววนซ้ำเป็นวิธีแก้ปัญหาที่ถูกต้องสำหรับการลบองค์ประกอบในลูป และคุณรู้ว่าสไตล์ลูป
for-each
ทำงานเหมือนกับตัววนซ้ำ แต่ก็ไม่ได้เป็นเช่นนั้นพิจารณารหัสต่อไปนี้:
ArrayList<String> list = new ArrayList<String>(Arrays.asList("a", "b", "c", "d")); for (String s : list) { if (s.equals("a")) list.remove(s); }
เราจะได้รับConcurrentModificationException
สิ่งที่ถูกต้องที่ต้องทำคือ:
ArrayList<String> list = new ArrayList<String>(Arrays.asList("a", "b", "c", "d")); Iterator<String> iter = list.iterator(); while (iter.hasNext()) { String s = iter.next(); if (s.equals("a")) { iter.remove(); } }
ในรูปแบบลูปnext()
ต้องเรียกเมธอดนี้ ก่อนไฟล์remove()
.for-each
คอมไพลเลอร์จะเรียกเมธอดremove()
จากนั้นเท่านั้นnext()
ซึ่งจะทำให้เกิดข้อผิดConcurrentModificationException
พลาดArrayList.iterator()
คุณ สามารถดูรหัส -
Hashtable
ขัดต่อHashMap
.เนื่องจากการใช้งานที่สอดคล้องกันHashtableจึงเป็นชื่อของโครงสร้างข้อมูล
แต่ในJavaชื่อของโครงสร้างข้อมูลคือ
HashMap
. ความแตกต่างที่สำคัญประการหนึ่งระหว่างHashtable
และHashMap
ก็คือ มีHashtable
การซิงโครไนซ์ ดังนั้นจึงไม่ควรใช้Hashtable
โดยHashMap
ที่ -
ใช้คอลเลกชันโดยไม่มีข้อจำกัดด้านเนื้อหา
В Java часто путают коллекции без ограничений по содержимому, и коллекции с маской по типу содержимого. К примеру, для множеств -
Set
это коллекция без ограничений по содержимому, аSet<?>
— коллекция у которой все-таки есть ограничения, но эти ограничения ничего на самом деле не ограничивают. Рассмотрим следующий code, гдеList
без ограничений используется в качестве параметра метода:public static void add(List list, Object o){ list.add(o); } public static void main(String[] args){ List<String> list = new ArrayList<String>(); add(list, 10); String s = list.get(0); }
Данный code выбросит исключение:
Exception in thread "main" java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String at …
Использование коллекций без ограничений по содержимому очень опасно, потому что вы не можете быть уверенными в том что там лежит внутри. А для того чтобы понять всю глубину разницы между
Set
,Set<?>
иSet<Object>
— почитайте вот эту и эту ссылки. -
Уровень доступа
Очень часто для полей класса разработчики используют модификатор доступа
public
. Так проще получить meaning поля напрямую. Правильнее использовать How можно более ограниченный доступ к членам класса. ArrayList
противLinkedList
Когда разработчики не знают чем отличается
ArrayList
отLinkedList
, они используют первый в силу его большей известности. Однако, есть огромная разница в производительности между ними. На самом деле, выбор между ними должен быть продиктован их внутренними особенностями —ArrayList
позволяет быстро производить доступ к произвольному элементу массива, аLinkedList
— быстро добавлять/удалять элементы в массиве. Почитайте статью по ссылке ArrayList vs. LinkedList чтобы понять причины их разной производительности.Mutable
(Изменяемый) противImmutable
(Неизменяемый)Неизменяемый an object имеет много преимуществ: простота, безопасность и т.д. Но он требует отдельного an object для каждого нового значения, и за слишком большое количество an objectов придется заплатить понижением производительности. Должен быть баланс при выборе между изменяемым и неизменяемым обьектом.
В основном чтобы избежать подготовки промежуточных an objectов используется изменяемый an object. Один из классических примеров это конкатенация большого количества строк. Если вы используете неизменяемый an object типа
String
, то вы создаете много an objectов, которые сразу попадут в сборщик мусора. Это тратит время и энергию процессора, поэтому правильное решение это использование изменяемых обьектов (напримерStringBuilder
).String result=""; for(String s: arr){ result = result + s; }
Еще один пример использования изменяемых an objectов — передача такого an object в метод. Это позволит вернуть результат в нем же, без создания лишних an objectов. При работе с an objectми большого размера, к примеру коллекциями, передача коллекции в метод для сортировки и возвращение результата в другой коллекции приводит к совершенно излишнему расходу ресурсов. (Ответ пользователя dasblinkenlight на Stack Overflow).
-
Конструкторы классов
Super
иSub
ข้อผิดพลาดในการคอมไพล์นี้มีสาเหตุมาจากข้อเท็จจริงที่ว่าคลาสบรรพบุรุษไม่ได้กำหนดคอนสตรัคเตอร์เริ่มต้นไว้ ในJavaเว้นแต่คุณจะระบุตัวสร้างคลาสด้วยตัวเอง คอมไพลเลอร์จะสร้างตัวสร้างเริ่มต้นที่ไม่ต้องมีอาร์กิวเมนต์ ถ้าคอนสตรัคเตอร์ถูกอธิบายไว้ในคลาส
Super
ว่าSuper(String s){}
คอมไพเลอร์เองก็จะไม่เพิ่มสิ่งใดเข้าไป นี่คือสิ่งที่เราเห็นในตัวอย่างของเราConstructor ของคลาส
Sub
ไม่ว่าอันไหนก็ตาม จะเรียก Constructor เริ่มต้นของคลาสSuper
เนื่องจากไม่มีการระบุอย่างอื่นอีก เนื่องจากไม่มีตัวสร้างเริ่มต้นในคลาสSuper
สิ่งนี้จะทำให้เกิดข้อผิดพลาดในการคอมไพล์วิธีแก้ปัญหาแรกสำหรับปัญหานี้คือการเพิ่มคอนสตรัคเตอร์เริ่มต้นให้กับคลาส
Super
public Super(){ System.out.println("Super"); }
ตัวเลือกที่สองคือการลบคอนสตรัคเตอร์ที่เราอธิบายออกจากคลาส
Super
เพื่อให้คอมไพเลอร์สร้างคอนสตรัคเตอร์เริ่มต้นและตัวเลือกสุดท้ายคือการเพิ่มการเรียก
super(value)
ตัวสร้างคลาสSub
เพื่อให้ตัวสร้างคลาสที่มีอยู่ถูกเรียกแทนตัวสร้างเริ่มต้นSuper
-
" " หรือตัวสร้าง?
มีสองวิธีในการสร้างสตริง:
//1. использовать двойные кавычки String x = "abc";
//2. использовать конструктор String y = new String("abc");
ความแตกต่างระหว่างพวกเขาคืออะไร?
คุณสามารถเข้าใจสิ่งนี้ได้จากตัวอย่างต่อไปนี้:
String a = "abcd"; String b = "abcd"; System.out.println(a == b); // True System.out.println(a.equals(b)); // True String c = new String("abcd"); String d = new String("abcd"); System.out.println(c == d); // False System.out.println(c.equals(d)); // True
หากต้องการเรียนรู้เพิ่มเติมเกี่ยวกับวิธีการจัดเก็บสตริงในหน่วยความจำ โปรดอ่านสร้างสตริง Java โดยใช้ "" หรือ Constructor? .
GO TO FULL VERSION