Разделете списък в Java

1. Общ преглед

В този урок ще илюстрирам как да разделя списък на няколко подлиста с даден размер.

За сравнително проста операция изненадващо няма поддръжка в стандартните API за събиране на Java. За щастие, както Guava, така и Apache Commons Collection са приложили операцията по подобен начин.

Тази статия е част от поредицата „ Java - Back to Basic “ тук на Baeldung.

2. Използвайте Guava за разделяне на списъка

Гуава улеснява разделянето Списъка в подсписъци от определен размер - чрез по Lists.partition операцията :

@Test public void givenList_whenParitioningIntoNSublists_thenCorrect() { List intList = Lists.newArrayList(1, 2, 3, 4, 5, 6, 7, 8); List
    
      subSets = Lists.partition(intList, 3); List lastPartition = subSets.get(2); List expectedLastPartition = Lists. newArrayList(7, 8); assertThat(subSets.size(), equalTo(3)); assertThat(lastPartition, equalTo(expectedLastPartition)); }
    

3. Използвайте Guava за разделяне на колекция

Разделянето на колекция също е възможно с Guava:

@Test public void givenCollection_whenParitioningIntoNSublists_thenCorrect() { Collection intCollection = Lists.newArrayList(1, 2, 3, 4, 5, 6, 7, 8); Iterable
    
      subSets = Iterables.partition(intCollection, 3); List firstPartition = subSets.iterator().next(); List expectedLastPartition = Lists. newArrayList(1, 2, 3); assertThat(firstPartition, equalTo(expectedLastPartition)); }
    

Имайте предвид, че дяловете са изгледи на подспис на оригиналната колекция - което означава, че промените в оригиналната колекция ще бъдат отразени в дяловете:

@Test public void givenListPartitioned_whenOriginalListIsModified_thenPartitionsChangeAsWell() { // Given List intList = Lists.newArrayList(1, 2, 3, 4, 5, 6, 7, 8); List
    
      subSets = Lists.partition(intList, 3); // When intList.add(9); // Then List lastPartition = subSets.get(2); List expectedLastPartition = Lists. newArrayList(7, 8, 9); assertThat(lastPartition, equalTo(expectedLastPartition)); }
    

4. Използвайте колекции Apache Commons, за да разделите списъка

Последните издания на Apache Commons Collections наскоро добавиха поддръжка и за разделяне на списък:

@Test public void givenList_whenParitioningIntoNSublists_thenCorrect() { List intList = Lists.newArrayList(1, 2, 3, 4, 5, 6, 7, 8); List
    
      subSets = ListUtils.partition(intList, 3); List lastPartition = subSets.get(2); List expectedLastPartition = Lists. newArrayList(7, 8); assertThat(subSets.size(), equalTo(3)); assertThat(lastPartition, equalTo(expectedLastPartition)); }
    

Няма съответна опция за разделяне на сурова колекция - подобно на дяла на Guava Iterables.part в колекциите на Commons.

И накрая, същото предупреждение се прилага и тук - полученият дял е изгледи на оригиналния списък.

5. Използвайте Java8 за разделяне на списъка

Сега нека видим как да използваме Java8 за разделяне на нашия списък.

5.1. Разделяне на колектори От

Можем да използваме Collectors.partitioningBy (), за да разделим списъка на 2 подлиста - както следва:

@Test public void givenList_whenParitioningIntoSublistsUsingPartitionBy_thenCorrect() { List intList = Lists.newArrayList(1, 2, 3, 4, 5, 6, 7, 8); Map
    
      groups = intList.stream().collect(Collectors.partitioningBy(s -> s > 6)); List
     
       subSets = new ArrayList
      
       (groups.values()); List lastPartition = subSets.get(1); List expectedLastPartition = Lists. newArrayList(7, 8); assertThat(subSets.size(), equalTo(2)); assertThat(lastPartition, equalTo(expectedLastPartition)); }
      
     
    

Забележка: Получените дялове не са изглед на основния списък, така че евентуалните промени в основния списък няма да повлияят на дяловете.

5.2. Групиране на колекционери

Също така можем да използваме Collectors.groupingBy (), за да разделим нашия списък на множество дялове:

@Test public final void givenList_whenParitioningIntoNSublistsUsingGroupingBy_thenCorrect() { List intList = Lists.newArrayList(1, 2, 3, 4, 5, 6, 7, 8); Map
    
      groups = intList.stream().collect(Collectors.groupingBy(s -> (s - 1) / 3)); List
     
       subSets = new ArrayList
      
       (groups.values()); List lastPartition = subSets.get(2); List expectedLastPartition = Lists. newArrayList(7, 8); assertThat(subSets.size(), equalTo(3)); assertThat(lastPartition, equalTo(expectedLastPartition)); }
      
     
    

Забележка: Точно както Collectors.partitioningBy () - получените дялове няма да бъдат засегнати от промени в основния списък.

5.3. Разделете списъка по разделител

Също така можем да използваме Java8 за разделяне на нашия списък по разделител:

@Test public void givenList_whenSplittingBySeparator_thenCorrect() { List intList = Lists.newArrayList(1, 2, 3, 0, 4, 5, 6, 0, 7, 8); int[] indexes = Stream.of(IntStream.of(-1), IntStream.range(0, intList.size()) .filter(i -> intList.get(i) == 0), IntStream.of(intList.size())) .flatMapToInt(s -> s).toArray(); List
    
      subSets = IntStream.range(0, indexes.length - 1) .mapToObj(i -> intList.subList(indexes[i] + 1, indexes[i + 1])) .collect(Collectors.toList()); List lastPartition = subSets.get(2); List expectedLastPartition = Lists. newArrayList(7, 8); assertThat(subSets.size(), equalTo(3)); assertThat(lastPartition, equalTo(expectedLastPartition)); }
    

Забележка: Използвахме „0“ като разделител - първо получихме индексите на всички елементи „0“ в списъка, след което разделихме списъка върху тези индекси.

6. Заключение

Представените тук решения използват допълнителни библиотеки - Guava или библиотеката Apache Commons Collections. И двете са много леки и изключително полезни като цяло, така че е напълно логично да имате един от тях на пътя на класа; ако обаче това не е опция - тук е показано решение само за Java.

Внедряването на всички тези примери и кодови фрагменти може да бъде намерено в GitHub - това е проект, базиран на Maven, така че трябва да е лесно да се импортира и да се изпълнява както е.