-
Konwersja tablicy na ArrayList .
Aby przekonwertować tablicę na ArrayList , programiści często używają tej metody:
List<String> list = Arrays.asList(arr);
Arrays.asList()
zwróci obiekt klasy ,ArrayList
który jest wewnętrzną, prywatną klasą statyczną(private static class)
klasyArrays
i nie jest to klasa.java.util.ArrayList.
Klasajava.util.Arrays.ArrayList
zawiera metodyset()
,,,, ale nie zawiera żadnych metod dodawania elementów, jej rozmiar jest stały . Aby stworzyć prawdziwy , wykonaj następujące czynności:get()
contains()
java.util.ArrayList
ArrayList<String> arrayList = new ArrayList<String>(Arrays.asList(arr));
Konstruktor klasy
java.util.ArrayList
może przyjąć jako parametr wszystkie obiekty implementujące interfejsCollection
, którego implementacja jest dziedziczona przez klasęjava.util.Arrays.ArrayList
(prywatna klasa statyczna ArrayList<E> rozszerza AbstractList<E> implementuje RandomAccess, java.io.Serializable).
-
Sprawdzanie tablicy pod kątem określonej wartości.
Programiści często to robią:
Set<String> set = new HashSet<String>(Arrays.asList(arr)); return set.contains(targetValue);
Kod działa, ale nie ma potrzeby konwertowania go
List
do formatuSet
. Konwersja naSet
zajmie więcej czasu. W rzeczywistości wszystko jest proste:Arrays.asList(arr).contains(targetValue);
Lub
for(String s: arr){ if(s.equals(targetValue)) return true; } return false;
Pierwsza metoda jest znacznie krótsza.
-
Usuwanie elementu z
List
pętliRozważ następujący kod, który usuwa elementy w pętli:
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);
Wniosek:
[b, d]
Okazuje się to poważnym błędem. Po usunięciu elementu jego rozmiar
List
ulega zmniejszeniu, a indeksy elementu ulegają zmianie.Unikaj więc tej metody, jeśli chcesz usunąć wiele elementów z pętli za pomocą indeksu.
Być może wiesz, że użycie iteratora jest właściwym rozwiązaniem do usuwania elementów w pętli i wiesz, że pętla stylu
for-each
działa jak iterator, ale tak nie jest.Rozważ następujący kod:
ArrayList<String> list = new ArrayList<String>(Arrays.asList("a", "b", "c", "d")); for (String s : list) { if (s.equals("a")) list.remove(s); }
Otrzymamy wyjątek ConcurrentModificationException .
Właściwą rzeczą do zrobienia jest:
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(); } }
Metodę
W pętlinext()
należy wywołać przed metodąremove()
.for-each
kompilator wywoła metodęremove()
i dopiero wtedynext()
, co zgłosi błądConcurrentModificationException
. Możesz spojrzeć na kodArrayList.iterator()
. -
Hashtable
przeciwkoHashMap
.Ze względu na odpowiednią implementację Hashtable jest nazwą struktury danych.
Ale w Javie nazwa struktury danych to
HashMap
. Jedną z kluczowych różnic międzyHashtable
iHashMap
jest to, że jestHashtable
zsynchronizowany, dlatego nie należy go używaćHashtable
tam, gdzieHashMap
.HashMap vs. Mapa Drzewa vs. Hashtable vs. PołączonaHashMapa .
-
Korzystaj ze zbiorów bez ograniczeń dotyczących zawartości
В Java часто путают коллекции без ограничений по содержимому, и коллекции с маской по типу содержимого. К примеру, для множеств -
Set
это коллекция без ограничений по содержимому, аSet<?>
— коллекция у которой все-таки есть ограничения, но эти ограничения ничего на самом деле не ограничивают. Рассмотрим следующий kod, где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); }
Данный kod выбросит исключение:
Exception in thread "main" java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String at …
Использование коллекций без ограничений по содержимому очень опасно, потому что вы не можете быть уверенными в том что там лежит внутри. А для того чтобы понять всю глубину разницы между
Set
,Set<?>
иSet<Object>
— почитайте вот эту и эту ссылки. -
Уровень доступа
Очень часто для полей класса разработчики используют модификатор доступа
public
. Так проще получить oznaczający поля напрямую. Правильнее использовать Jak можно более ограниченный доступ к членам класса. ArrayList
противLinkedList
Когда разработчики не знают чем отличается
ArrayList
отLinkedList
, они используют первый в силу его большей известности. Однако, есть огромная разница в производительности между ними. На самом деле, выбор между ними должен быть продиктован их внутренними особенностями —ArrayList
позволяет быстро производить доступ к произвольному элементу массива, аLinkedList
— быстро добавлять/удалять элементы в массиве. Почитайте статью по ссылке ArrayList vs. LinkedList чтобы понять причины их разной производительности.Mutable
(Изменяемый) противImmutable
(Неизменяемый)Неизменяемый obiekt имеет много преимуществ: простота, безопасность и т.д. Но он требует отдельного obiektа для каждого нового значения, и за слишком большое количество obiektов придется заплатить понижением производительности. Должен быть баланс при выборе между изменяемым и неизменяемым обьектом.
В основном чтобы избежать подготовки промежуточных obiektов используется изменяемый obiekt. Один из классических примеров это конкатенация большого количества строк. Если вы используете неизменяемый obiekt типа
String
, то вы создаете много obiektов, которые сразу попадут в сборщик мусора. Это тратит время и энергию процессора, поэтому правильное решение это использование изменяемых обьектов (напримерStringBuilder
).String result=""; for(String s: arr){ result = result + s; }
Еще один пример использования изменяемых obiektов — передача такого obiektа в метод. Это позволит вернуть результат в нем же, без создания лишних obiektов. При работе с obiektами большого размера, к примеру коллекциями, передача коллекции в метод для сортировки и возвращение результата в другой коллекции приводит к совершенно излишнему расходу ресурсов. (Ответ пользователя dasblinkenlight на Stack Overflow).
-
Конструкторы классов
Super
иSub
Ten błąd kompilacji jest spowodowany faktem, że klasa przodka nie ma zdefiniowanego konstruktora domyślnego. W Javie , jeśli sam nie określisz konstruktora klasy, kompilator utworzy domyślny konstruktor, który nie wymaga żadnych argumentów. Jeśli konstruktor jest opisany w klasie
Super
jakoSuper(String s){}
, sam kompilator nic nie doda. To właśnie widzimy na naszym przykładzie.Konstruktor klasy
Sub
, nieważne który, wywoła domyślny konstruktor klasySuper
, ponieważ nie określono nic innego. Ponieważ w klasie nie ma domyślnego konstruktoraSuper
, spowoduje to błąd kompilacji.Pierwszym rozwiązaniem tego problemu jest dodanie domyślnego konstruktora do klasy
Super
public Super(){ System.out.println("Super"); }
Drugą opcją jest usunięcie opisanego przez nas konstruktora z klasy,
Super
dzięki czemu kompilator utworzy konstruktor domyślny.Ostatnią opcją jest dodanie wywołania
super(value)
konstruktorów klas,Sub
dzięki czemu zamiast konstruktora domyślnego zostanie wywołany istniejący konstruktor klasySuper
-
" " czy konstruktor?
Istnieją dwa sposoby tworzenia ciągu znaków:
//1. использовать двойные кавычки String x = "abc";
//2. использовать конструктор String y = new String("abc");
Jaka jest różnica między nimi?
Można to zrozumieć na podstawie następujących przykładów:
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
Aby dowiedzieć się więcej o przechowywaniu ciągów w pamięci, przeczytaj artykuł Tworzenie ciągu Java przy użyciu „” lub konstruktora? .
GO TO FULL VERSION