JavaRush /Java блогу /Random-KY /Java коллекциялары жөнүндө эң мыкты 10 суроо
FedoraLinux
Деңгээл
Москва

Java коллекциялары жөнүндө эң мыкты 10 суроо

Группада жарыяланган
Макала " Java Collections жөнүндө эң мыкты 10 суроо " макаласынын котормосу . Төмөндө Stackowerflow'та берилген жана талкууланган Java коллекциялары жөнүндө эң популярдуу суроолор. Бул суроолорду кароодон мурун класстын иерархиясынын диаграммасын карап чыксаңыз жакшы болмок. 1. ArrayListтин ордуна LinkedListти качан колдонуу керек? ArrayList чындыгында массив; анын элементтерине түздөн-түз индекс аркылуу кирүүгө болот. Эгерде массив толуп кетсе, анда көбүрөөк орун менен жаңысы зарыл болуп калат. Бардык элементтерди жайгаштыруу жана жылдыруу O(n) убакытты талап кылат. Ошондой эле, элементтерди кошуу жана алып салуу массивдеги бар элементтерди жылдыруу үчүн зарыл. Бул, балким, ArrayListти колдонуудагы эң чоң ыңгайсыздык. LinkedList - бул элемент шилтемелеринин кош тизмеси. Ошентип, борбордогу элементке жетүү үчүн, барактын башынан аягына чейин издөө керек. Экинчи жагынан, LinkedListке элементти кошуу жана алып салуу тезирээк, анткени бул операциялар тизменин өзүн гана өзгөртөт. Эң начар мезгилдер төмөндө салыштырылат:
Метод Arraylist LinkedList
алуу (индекс) O(1) O(n)
кошуу(E) O(n) O(1)
кошуу(E, индекс) O(n) O(n)
алып салуу(индекс) O(n) O(n)
Iterator.remove() O(n) O(1)
Iterator.add(E) O(n) O(1)
Иштөө убактысына карабастан, эстутумдун колдонулушу чоң тизмелер үчүн өзүнчө каралышы керек. LinkedListте ар бир түйүндө мурунку жана кийинки түйүндөрдү байланыштыруу үчүн кеминде эки кошумча көрсөткүч болушу керек, ал эми ArrayListте элементтердин массивдери гана керектелет. ArrayList, LinkedList жана Vector тизмелерин көбүрөөк салыштыруу . 2. Коллекцияны итерациялоо учурунда элементтерди алып салуу үчүн эффективдүү эквивалент. Итерация учурунда коллекцияны өзгөртүүнүн (элементтерди алып салуу) жалгыз туура жолу Iterator.remove() колдонуу болуп саналат . Мисалы: Эң кеңири тараган ката: Сиз жогорудагы codeду иштетип жатканда ConcurrentModificationException аласыз . Бул итератор бүт тизме боюнча жылдыруу үчүн түзүлгөндүктөн болот, бирок ошол эле учурда барак Iterator.remove() чалуу менен өзгөртүлөт. Бул өзгөчөлүк үчүн documentтерде жазылгандай, Iterator itr = list.iterator(); while(itr.hasNext()) { // do something itr.remove(); } for(Integer i: list) { list.remove(i); }
"бир жип коллекцияны өзгөртүүгө, ал эми экинчи жип анын үстүнөн итерацияланууга жалпысынан жол берилбейт."
Жалпысынан алганда, бир жип коллекцияны башка жиптен өтүп жатканда өзгөртүүгө жол берилбейт. 3. Тизмени int[] массивине кантип айландыруу керек? Муну жасоонун эң оңой жолу - Apache Commons Lang китепканасында жайгашкан ArrayUtils колдонуу . JDKда бул туюнтма үчүн кыска жол жок. List.toArray() функциясын колдоно албасыңызды унутпаңыз, анткени бул туюнтма Тизмени бүтүн санга[] айлантат (ал примитивдүү түр эмес ). Төмөнкү вариант туура жол болмок: 4. int[] массивин Тизмеге кантип айландыруу керек? Эң оңой жолу - жогорудагыдай Apache Commons Lang китепканасында ArrayUtils колдонуу . Ошондой эле, JDKда бул туюнтма үчүн кыска жол жок. 5. Коллекцияны чыпкалоонун эң жакшы жолу кайсы? Функционалдуулукту жогорулатуу үчүн Guava же Apache Commons Lang сыяктуу үчүнчү тараптын пакеттерин колдоно аласыз . Бул эки пакетте тең filter() ыкмасы бар ( Guavaдан Collections2 классында жана Apacheден CollectionUtils ). filter() методу берилген Предикатка дал келген элементтерди кайтарат. JDKда баары татаалыраак. Жакшы жаңылык, предикаттар Java 8ге кошулат , бирок азыр сиз бүт коллекцияны кайталоо үчүн Iterator колдонушуңуз керек. Албетте, сиз жаңы Predicate интерфейси менен таанышып, Guava жана Apache басып өткөн жолду туурай аласыз. Эми коллекцияны чыпкалоо үчүн төмөнкү codeду колдонсок болот: 6. Тизмени Set'ке кантип оңой айландырса болот? Теңдикти кантип аныктагыңыз келгенине жараша муну жасоонун эки жолу бар. Коддун биринчи бөлүгү тизмени HashSetке салат. Бул учурда дубликат негизинен hashCode() менен аныкталат. Эреже катары, бул иштейт. Бирок салыштыруу жолун эске алуу керек болсо, анда codeдун экинчи бөлүгүн колдонсоңуз жакшы болмок, анда сиз өзүңүздүн компараторуңузду аныктай аласыз. 7. ArrayListтен кайталанган элементтерди кантип алып салсам болот? Бул суроо жогорудагы суроого кандайдыр бир деңгээлде байланыштуу. Эгерде ArrayListтеги элементтердин тартиби сиз үчүн маанилүү болбосо, дубликаттарды алып салуу үчүн баракты топтомго жайгаштыруу, андан кийин аны кайра Тизмеге кайтаруу акылдуу кадам болот. Төмөндө бир мисал келтирилген. Эгер элементтердин тартиби сиз үчүн маанилүү болсо, анда тизмени стандарттык JDKдагы LinkedHashSetке жайгаштыруу менен тартипти камсыз кылууга болот. 8. Сорттолгон коллекция int[] array = ArrayUtils.toPrimitive(list.toArray(new Integer[0])); int[] array = new int[list.size()]; for(int i=0; i < list.size(); i++) { array[i] = list.get(i); } List list = Arrays.asList(ArrayUtils.toObject(array)); int[] array = {1,2,3,4,5}; List list = new ArrayList (); for(int i: array) { list.add(i); } Iterator itr = list.iterator(); while(itr.hasNext()) { int i = itr.next(); if (i > 5) { // filter all ints bigger than 5 itr.remove(); } } 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(); } } } } filter(list, new Predicate () { public boolean test(Integer i) { return i <= 5; } }); Set set = new HashSet (list); Set set = new TreeSet (aComparator); set.addAll(list); ArrayList** list = ... // initial a list with duplicate elements Set set = new HashSet (list); list.clear(); list.addAll(set); Java'да сорттолгон коллекцияны колдоонун бир нече жолу бар. Алардын баары табигый тартипте же көрсөтүлгөн компаратор менен чогултууну камсыз кылат. Табигый тартип болгон учурда, сиз элементте Салыштырылуучу интерфейсти ишке ашырууңуз керек.
  1. Collections.sort() Тизмени иреттей алат. Java documentациясында айтылгандай, бул сорт туруктуу жана n log(n) иштешине кепилдик берет.
  2. PriorityQueue иреттүү кезекти камсыз кылат. PriorityQueue менен Collections.sort() ортосундагы айырма PriorityQueue ар дайым кезек тартибин сактап турат, бирок сиз кезектин биринчи элементин гана ала аласыз. PriorityQueue.get(4) сыяктуу элементке туш келди кире албайсыз.
  3. Коллекцияда эч кандай дубликаттар жок болсо, TreeSet тандай аласыз . PriorityQueue сыяктуу эле, TreeSet ар дайым иреттелген топтомду сактап турат. Сиз TreeSetтен эң кичине же эң чоң элементти ала аласыз, бирок сиз дагы эле элементтерге туш келди кире албайсыз.
Жөнөкөй сөз менен айтканда, Collections.sort() бир жолку иреттелген тизмени берет. PriorityQueue жана TreeSet элементтерге индекстелген жеткorктүүлүктүн жоктугунан улам ар дайым иреттелген коллекцияны сактап турушат. 9. Collections.emptyList() же жаңы инстанция Ушул эле суроо emptyMap() жана emptySet() үчүн колдонулат. Эки ыкма тең бош тизмени кайтарат, бирок Collections.emptyList() өзгөрүлгүс тизме. Бул "бош" тизмеге жаңы элементтерди кошууга болбойт дегенди билдирет. Фондо Collections.emptyList() ыкмасына ар бир чалуу иш жүзүндө бош тизменин жаңы инстанциясын түзбөйт. Анын ордуна, ал буга чейин болгон бош инстанцияны кайра колдонот. Эгер сиз Singleton менен дизайн үлгүсү катары тааныш болсоңуз , анда эмнени билдирерин түшүнүшүңүз керек. Бул тез-тез чалса жакшыраак иштеши керек . 10 Коллекцияны көчүрүү, Collections.copy() Булак тизмесин көздөгөн тизмеге көчүрүүнүн эки жолу бар. Бир жолу - ArrayList конструкторун колдонуу. Дагы бир жолу Collections.copy() ыкмасын колдонуу . Биринчи сапта эскертүү: биз эң аз дегенде баштапкы тизменин узундугуна барабар болгон тизмени бөлүп жатабыз, анткени коллекциялар жөнүндө Java documentациясында мындай дейт: ArrayList dstList = new ArrayList (srcList);
Бара турган жерлердин тизмеси булак тизмесинен кем эмес болушу керек.
Бул акыркы тизме түп нускасынан кыска болбошу керек дегенди билдирет. Эки ыкма тең тайыз көчүрүү болуп саналат. Ошентип, бул эки ыкманын ортосунда кандай айырма бар? Биринчиден, Collections.copy() dstListтин коллекция сыйымдуулугун кайра бөлүштүрбөйт, ал тургай, dstListте srcListтин бардык элементтерин камтуу үчүн жетиштүү орун жок. Анын ордуна, ал IndexOutOfBoundsException ыргытат . Мунун кандайдыр бир пайдасы барбы деп сурашы мүмкүн. Себеби, бул ыкма өз убагында сызыктуу иштешин камсыз кылат. Бул ArrayList конструкторунда эстутумду кайра бөлүштүрүүнүн ордуна массивдерди кайра колдонгуңуз келгенде да ылайыктуу. Корутундунун ордуна, макаланы окугандан кийин дагы суроолоруңуз болсо, аларды комментарийлерде берүүдөн тартынбаңыз. Ошондой эле котормодо так эмес же башка ката тапсаңыз, анда ПМге жазыңыз, ал оңдолот, сизге ыраазычылык билдирилет. Original. ArrayList dstList = new ArrayList (srcList.size()); Collections.copy(dstList, srcList);
Комментарийлер
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION