JavaRush /Java блогы /Random-KK /Java тіліндегі жинақтар туралы ең жақсы 10 сұрақ
FedoraLinux
Деңгей
Москва

Java тіліндегі жинақтар туралы ең жақсы 10 сұрақ

Топта жарияланған
Мақала мақаланың аудармасы болып табылады « Java жинақтары туралы ең жақсы 10 сұрақ » . Төменде Stackowerflow сайтында қойылған және талқыланған Java-дағы жинақтар туралы ең танымал сұрақтар берілген. Осы сұрақтарды қарастырмас бұрын, сыныптың иерархиялық диаграммасын қарастырған дұрыс. 1. ArrayList орнына LinkedList қай кезде қолданылады? ArrayList - бұл массив; оның элементтеріне индекс арқылы тікелей қол жеткізуге болады. Егер массив толып кетсе, көбірек орыны бар жаңасы қажет болады. Барлық элементтерді орналастыру және жылжыту O(n) уақытын алады. Сондай-ақ, элементтерді қосу және жою массивтегі бар элементтерді жылжыту үшін қажет. Бұл ArrayList пайдаланудың ең үлкен қолайсыздығы болуы мүмкін. LinkedList - элементтер сілтемелерінің қос тізімі. Осылайша, орталықтағы элементке қол жеткізу үшін парақтың басынан аяғына дейін іздеу керек. Екінші жағынан, LinkedList ішіндегі элементті қосу және жою жылдамырақ, себебі бұл әрекеттер тізімнің өзін ғана өзгертеді. Ең нашар уақыт төменде салыстырылады:
Әдіс Массив тізімі LinkedList
алу (индекс) O(1) O(n)
қосу(Е) 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() шақыру арқылы өзгертіледі. Осы ерекшелік үшін құжаттамада жазылғандай, 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() функциясын пайдалана алмайтыныңызды есте сақтаңыз, себебі бұл өрнек Тізімді Integer[] түріне түрлендіреді (ол қарабайыр түр емес ). Дұрыс жол келесі опция болады: 4. int[] массивін Тізімге қалай түрлендіруге болады? Ең оңай жолы - жоғарыдағыдай Apache Commons Lang кітапханасында ArrayUtils пайдалану . Сондай-ақ, JDK-де бұл өрнектің таңбашасы жоқ. 5. Жинақты сүзудің ең жақсы жолы қандай? Функционалдылықты арттыру үшін Guava немесе Apache Commons Lang сияқты үшінші тарап пакеттерін пайдалануға болады . Бұл пакеттердің екеуінде filter() әдісі бар ( Guava-дан Collections2 класында және Apache-тен CollectionUtils ). filter() әдісі берілген Предикатқа сәйкес келетін элементтерді қайтарады. JDK-де бәрі күрделірек. Жақсы жаңалық, предикаттар Java 8 жүйесінде қосылады , бірақ әзірге бүкіл жинақты қайталау үшін Итераторды пайдалану қажет. Әрине, сіз жаңа 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 құжаттамасында айтылғандай, бұл сұрыптау тұрақты және n log(n) өнімділігіне кепілдік береді.
  2. PriorityQueue реттелген кезекті қамтамасыз етеді. PriorityQueue мен Collections.sort() арасындағы айырмашылық PriorityQueue барлық уақытта кезек тәртібін сақтайды, бірақ сіз тек бірінші элементті ала аласыз. PriorityQueue.get(4) сияқты элементке кездейсоқ қол жеткізе алмайсыз.
  3. Жинақта көшірмелер болмаса, TreeSet параметрін таңдауға болады . Сондай-ақ PriorityQueue сияқты, TreeSet реттелген жиынды барлық уақытта қолдайды. Сіз TreeSet ішінен ең кіші немесе ең үлкен элементті ала аласыз, бірақ әлі де элементтерге кездейсоқ қатынаса алмайсыз.
Қарапайым тілмен айтқанда, Collections.sort() бір реттік реттелген тізімді ұсынады. PriorityQueue және TreeSet элементтерге индекстелген қол жеткізудің жоқтығы есебінен барлық уақытта реттелген жинақты қолдайды. 9. Collections.emptyList() немесе жаңа данасы Бірдей сұрақ emptyMap() және emptySet() үшін де қолданылады. Екі әдіс бос тізімді қайтарады, бірақ Collections.emptyList() өзгермейтін тізім болып табылады. Бұл «бос» тізімге жаңа элементтерді қосу мүмкін емес дегенді білдіреді. Фондық режимде Collections.emptyList() әдісіне әрбір шақыру іс жүзінде бос тізімнің жаңа данасын жасамайды. Оның орнына ол бұрыннан бар бос дананы қайта пайдаланады. Егер сіз Singleton-мен дизайн үлгісі ретінде таныс болсаңыз , нені білдіретінін түсінуіңіз керек. Бұл жиі шақырылатын болса, сізге жақсы өнімділік береді . 10 Жинақты көшіру, Collections.copy() Бастапқы тізімді тағайындалған тізімге көшірудің екі жолы бар. Бір жолы ArrayList конструкторын пайдалану болып табылады. Басқа әдіс Collections.copy() әдісін пайдалану болып табылады . Бірінші жолдағы ескерту: біз ең болмағанда бастапқы тізімнің ұзындығымен бірдей ұзындықтағы тізімді бөліп жатырмыз, себебі коллекциялар туралы Java құжаттамасында былай делінген: ArrayList dstList = new ArrayList (srcList);
Тағайындалған орындар тізімі кем дегенде бастапқы тізімдегідей ұзын болуы керек.
Бұл түпкілікті тізім түпнұсқадан қысқа болмауы керек дегенді білдіреді. Екі әдіс те таяз көшіру болып табылады. Сонымен, бұл екі әдістің айырмашылығы неде? Біріншіден, Collections.copy() dstList-тің коллекция сыйымдылығын қайта бөлмейді, тіпті dstList-те srcList-тің барлық элементтерін қамту үшін жеткілікті орын болмаса да. Оның орнына ол IndexOutOfBoundsException шығарады . Мұның пайдасы бар ма деп сұрауы мүмкін. Себебі, бұл әдіс уақыт бойынша сызықтық жұмыс істеуін қамтамасыз етеді. Бұл ArrayList конструкторында жадты қайта бөлуден гөрі массивтерді қайта пайдаланғыңыз келсе де қолайлы. Қорытындының орнына Егер мақаланы оқығаннан кейін сізде әлі де сұрақтар болса, оларды түсініктемелерде сұраңыз. Сондай-ақ аудармада қандай да бір қателік немесе басқа қателерді байқасаңыз, ПМ-ге жазыңыз, ол түзетіледі, сізге алғыс айтылады. Түпнұсқа. ArrayList dstList = new ArrayList (srcList.size()); Collections.copy(dstList, srcList);
Пікірлер
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION