JavaRush /Java Blog /Random-TL /Nangungunang 10 Mga Tanong tungkol sa Mga Koleksyon sa Ja...
FedoraLinux
Antas
Москва

Nangungunang 10 Mga Tanong tungkol sa Mga Koleksyon sa Java

Nai-publish sa grupo
Ang artikulo ay pagsasalin ng artikulong " Nangungunang 10 tanong tungkol sa Mga Koleksyon ng Java " . Nasa ibaba ang mga pinakasikat na tanong tungkol sa mga koleksyon sa Java, tinanong at tinalakay sa Stackowerflow. Bago mo tingnan ang mga tanong na ito, makabubuting tingnan ang class hierarchy diagram. 1. Kailan gagamitin ang LinkedList sa halip na ArrayList? Ang ArrayList ay sa katunayan isang array; ang mga elemento nito ay maaaring direktang ma-access sa pamamagitan ng index. Kung umapaw ang array, kinakailangan ang bago na may mas maraming espasyo. Ang paglalagay at paglipat ng lahat ng elemento ay tatagal ng O(n) oras. Gayundin, ang pagdaragdag at pag-alis ng mga elemento ay kinakailangan upang ilipat ang mga umiiral na elemento sa array. Ito marahil ang pinakamalaking abala sa paggamit ng ArrayList. Ang LinkList ay isang dobleng listahan ng mga link ng elemento. Kaya, upang ma-access ang elemento sa gitna, kailangan mong maghanap mula sa pinakadulo simula hanggang sa dulo ng sheet. Sa kabilang banda, ang pagdaragdag at pag-alis ng isang elemento sa isang LinkedList ay mas mabilis dahil ang mga pagpapatakbong ito ay nagbabago lamang sa listahan mismo. Ang pinakamasamang panahon ay inihambing sa ibaba:
Pamamaraan Arraylist LinkedList
makuha (index) O(1) O(n)
magdagdag (E) O(n) O(1)
idagdag(E, index) O(n) O(n)
alisin (index) O(n) O(n)
Iterator.remove() O(n) O(1)
Iterator.add(E) O(n) O(1)
Sa kabila ng oras ng pagtakbo, ang paggamit ng memorya ay dapat isaalang-alang nang paisa-isa para sa malalaking listahan. Sa isang LinkedList, ang bawat node ay dapat magkaroon ng hindi bababa sa dalawang karagdagang mga pointer upang maiugnay ang nakaraan at susunod na mga node, habang sa isang ArrayList, isang hanay ng mga elemento lamang ang kailangan. Higit pang mga paghahambing ng mga listahan ng ArrayList, LinkedList at Vector . 2. Mahusay na katumbas para sa pag-alis ng mga elemento sa panahon ng pag-ulit ng koleksyon Ang tanging tamang paraan upang baguhin (pag-alis ng mga elemento) ang isang koleksyon sa panahon ng pag-ulit ay ang paggamit ng Iterator.remove() . Halimbawa: Ang pinakakaraniwang error ay: Makakakuha ka ng ConcurrentModificationException habang pinapatakbo ang code sa itaas. Nangyayari ito dahil nabuo ang iterator upang lumipat sa buong listahan, ngunit sa parehong oras ay binago ang sheet sa pamamagitan ng pagtawag sa Iterator.remove(). Gaya ng nakasulat sa dokumentasyon para sa pagbubukod na ito, Iterator itr = list.iterator(); while(itr.hasNext()) { // do something itr.remove(); } for(Integer i: list) { list.remove(i); }
"Sa pangkalahatan ay hindi pinapayagan para sa isang thread na baguhin ang isang koleksyon habang ang isa pang thread ay umuulit dito."
В целом, недопустима ситуация, при которой одна нить (thread) изменяет коллекцию в то время, How другая нить проходит по ней. 3. Как конвертировать List в массив int[]? Самым легким путем для этого является использование ArrayUtils, располагающийся в библиотеке Apache Commons Lang. int[] array = ArrayUtils.toPrimitive(list.toArray(new Integer[0])); В JDK нету сокращения для этого выражения. Запомните, что Вы не можете использовать List.toArray() потому, что это выражение конвертирует List в Integer[] (который не является примитивным типом, прим. перевод.). Правильным путем будет следующий вариант: int[] array = new int[list.size()]; for(int i=0; i < list.size(); i++) { array[i] = list.get(i); } 4. Как конвертировать массив int[] в List? Самым простым способом также является использование ArrayUtils в библиотеке Apache Commons Lang, How и выше. List list = Arrays.asList(ArrayUtils.toObject(array)); Также, в JDK нету сокращения для этого выражения. int[] array = {1,2,3,4,5}; List list = new ArrayList (); for(int i: array) { list.add(i); } 5. Каким образом лучше фильтровать коллекцию? Вы можете использовать сторонние пакеты, такие, How Guava or Apache Commons Lang для увеличения функционала. Оба этих пакета имеют метод filter() (в классе Collections2 от Guava и CollectionUtils от Apache). Метод filter() вернет элементы, которые совпадают со взятым Предикатом (Predicate). В JDK все сложнее. Хорошие новости состоят в том, что в Java 8 предикаты будут добавлены ( уже добавлены, прим. перевод.), но сейчас Вам необходимо использовать Iterator для перемещения по всей коллекции. Iterator itr = list.iterator(); while(itr.hasNext()) { int i = itr.next(); if (i > 5) { // filter all ints bigger than 5 itr.remove(); } } Конечно, Вы можете имитировать тот путь, которому следуют Guava и Apache, познакомившись с новым интерфейсом Predicate. public interface Predicate { boolean test(T o); } public static void filter(Collection collection, Predicate predicate) { if ((collection != null) && (predicate != null)) { Iterator itr = collection.iterator(); while(itr.hasNext()) { T obj = itr.next(); if (!predicate.test(obj)) { itr.remove(); } } } } Теперь мы можем использовать следующий code для фильтраци коллекции: filter(list, new Predicate () { public boolean test(Integer i) { return i <= 5; } }); 6. Как легко конвертировать List в Set? Существует два пути для этого, в зависимости от того, How Вы хотите определять equalsство. Первый кусок codeа помещает список в HashSet. Дубликат в таком случае определяется в основном по hashCode(). Как правило, это будет работать. Но если Вам нужно учитывать путь сравнения, то будел лучше использовать вторую часть codeа, где Вы можете определить Ваш собственный компаратор. Set set = new HashSet (list); Set set = new TreeSet (aComparator); set.addAll(list); 7. Как я могу удалить повторяющиеся элементы из ArrayList? Этот вопрос в некоторой степени связан с вопросом выше. Если для Вас не имеет значения порядок элементов в ArrayList, умным ходом будет поместить лист в набор (Set) для удаления дублиуатов, а после этого вернуть назад в список (List). Ниже пример. ArrayList** list = ... // initial a list with duplicate elements Set set = new HashSet (list); list.clear(); list.addAll(set); Если для Вас имеет meaning порядок элементов, то порядок может быть обеспечен путем помещения списка в LinkedHashSet, который есть в стандартном JDK. 8. Сортированная коллекция Существует несколько путей для поддержки сортированной коллекции в Java. Все из них обеспечивают коллекцию в натуральном порядке or по указанному компаратору. В случае с натуральным порядком Вам также нужно реализовать интерфейс Comparable в элементе.
  1. Collections.sort() может отсортировать List. Как указано в documentации Java, эта sorting стабильна и гарантирует производительность n log(n).
  2. PriorityQueue обеспечивает упорядоченную очередь. Различие между PriorityQueue и Collections.sort() в том, что PriorityQueue поддерживает порядок очереди все время, но Вы можете получить только первый элемент очереди. Вы не можете получить случайный доступ к элементу, например, How PriorityQueue.get(4).
  3. Если нету дубликатов в коллекции, можно выбрать TreeSet. Также, How и PriorityQueue, TreeSet поддерживает упорядоченный набор все время. Вы можете получить самый маленьний or самыый большой элемент из TreeSet, но вы все равно не можете иметь случайный доступ к elementм.
Проще говоря, Collections.sort() обеспечивает одноразовый упорядоченный список. PriorityQueue и TreeSet поддерживает упорядоченную коллекцию постоянно, за что приходится платить отсутствием индексированного доступа к elementм. 9. Collections.emptyList() or новый экземпляр Тот же вопрос применяется к emptyMap() и emptySet(). Оба метода возвращают пустой список, но Collections.emptyList() непреложный (immutable) список. Это означает, что вы не можете добавлять новые элементы к "пустому" списку. На фоне, каждый вызов метода Collections.emptyList() фактически не создает новый экземпляр пустого списка. Вместо этого, оно будет использовать снова уже существующий пустой экземпляр. Если Вы знакомы с синглтоном (Singleton, тыц, прим. перевод.) How с паттерном проектирования, Вы должны понять что имеется в виду. Это должно Вам дать б ольшую производительность, если вызывается часто. 10 Копирование коллекции, Collections.copy() Существует два способа копирования исходного списка в назначенный. Один путь - использование конструктора ArrayList. ArrayList dstList = new ArrayList (srcList); Иной способ - использование метода Collections.copy(). Обратите внимание на первую строку: мы выделяем список How минимум такой же длины, что и длина исходного списка, потому что в documentации Java о коллекциях сказано:
The destination list must be at least as long as the source list.
What означает, что конечный список должен быть не короче, чем исходный. ArrayList dstList = new ArrayList (srcList.size()); Collections.copy(dstList, srcList); Оба метода являются поверхностным копироваием (shallow copy). Так Howая же разница между этими двумя методами? Во-первых, Collections.copy() не будет перераспределять вместимость коллекции dstList, даже если dstList не будет иметь достаточно пространства для содержания всех элементов из srcList. Вместо этого, он будет бросать IndexOutOfBoundsException. Можно спросить, есть ли польза от этого. Причина в том, что это гарантирует то, что метод запускается линейно по времени. Также, это подходит в случае, когда Вы хотите использовать снова массивы, а не выделять снова память в конструкторе ArrayList. Вместо заключения Если после прочтения статьи у Вас еще остались вопросы, смело задавайте их в комментарии. Также, если Вы нашли Howую-либо неточность в переводе or еще Howую-либо ошибку, то пишите в ЛС, будет поправлена, а Вам будет спасибо. Оригинал.
Mga komento
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION