-
Перетворення масиву в 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(private static class ArrayList<E> extends AbstractList<E> implements 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<?>- колекція у якої все-таки є обмеження, але ці обмеження нічого насправді не обмежують. Розглянемо наступний код, де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); }Цей код викине виняток:
Exception in thread "main" java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String at …Використання колекцій без обмежень за вмістом дуже небезпечне, тому що ви не можете бути впевненими, що там лежить усередині. А для того щоб зрозуміти всю глибину різниці між ,
SetіSet<?>-Set<Object>почитайте ось це посилання . -
Рівень доступу
Найчастіше для полів класу розробники використовують модифікатор доступу
public. Так простіше отримати значення поля безпосередньо. Правильніше використовувати якомога обмеженіший доступ до членів класу. ArrayListпротиLinkedListКоли розробники не знають чим відрізняється
ArrayListвідLinkedList, вони використовують перший з його більшої популярності. Однак, є величезна різниця у продуктивності між ними. Насправді вибір між ними повинен бути продиктований їх внутрішніми особливостями —ArrayListдозволяє швидко здійснювати доступ до довільного елементу масиву, аLinkedList— швидко додавати/видаляти елементи в масиві. Почитайте статтю за посиланням ArrayList vs. LinkedList щоб зрозуміти причини їхньої різної продуктивності.Mutable(Змінний) протиImmutable(Незмінний)Незмінний об'єкт має багато переваг: простота, безпека тощо. Але він вимагає окремого об'єкта для кожного нового значення, і за дуже багато об'єктів доведеться заплатити зниженням продуктивності. Повинен бути баланс при виборі між об'єктом, що змінюється і незмінним.
В основному щоб уникнути підготовки проміжних об'єктів використовується об'єкт, що змінюється. Один із класичних прикладів це конкатенація великої кількості рядків. Якщо ви використовуєте незмінний об'єкт типу
String, то ви створюєте багато об'єктів, які відразу потраплять до збирача сміття. Це витрачає час і енергію процесора, тому правильне рішення це використання об'єктів, що змінюються (наприкладStringBuilder).String result=""; for(String s: arr){ result = result + s; }Ще один приклад використання об'єктів, що змінюються - передача такого об'єкта в метод. Це дозволить повернути результат у ньому без створення зайвих об'єктів. Працюючи з об'єктами великого розміру, наприклад колекціями, передача колекції в спосіб сортування і повернення результату до іншої колекції призводить до зайвої витрати ресурсів. ( Відповідь користувача dasblinkenlight на Stack Overflow ).
-
Конструктори класів
SuperтаSub
Ця помилка компіляції викликана тим, що у класу-предка не визначено конструктора за умовчанням. У Java , якщо ви самі не опишите конструктор класу, компілятор сам створить конструктор за замовчуванням, який не вимагає жодних аргументів. Якщо ж конструктор описаний у класі ,
SuperякSuper(String s){}компілятор сам нічого додавати не буде. Що ми й спостерігаємо у нашому прикладі.Конструктор класу
Sub, не важливо який з них, викличе конструктор за умовчанням класуSuper, оскільки не вказано нічого іншого. Оскільки конструктора за умовчанням у класіSuperнемає, це призведе до помилки компіляції.Перший варіант вирішення цієї проблеми - додати конструктор за замовчуванням до класу
Superpublic 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Для того щоб докладніше дізнатися про те, як рядки зберігаються в пам'яті, читайте Create Java String Using "" or Constructor? .
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ