Efficient way to divide a list into lists of n size

前端 未结 14 1196
无人共我
无人共我 2020-11-27 16:59

I have an ArrayList, which I want to divide into smaller Lists of n size, and perform an operation on each. My current method of doing this is

implemented with Array

相关标签:
14条回答
  • 2020-11-27 17:35

    You'll want to do something that makes use of List.subList(int, int) views rather than copying each sublist. To do this really easily, use Guava's Lists.partition(List, int) method:

    List<Foo> foos = ...
    for (List<Foo> partition : Lists.partition(foos, n)) {
      // do something with partition
    }
    

    Note that this, like many things, isn't very efficient with a List that isn't RandomAccess (such as a LinkedList).

    0 讨论(0)
  • 2020-11-27 17:35

    // Testing data

    List<Integer> list = Arrays.asList(0, 1, 2,     3, 4, 5,    6, 7, 8,    9);
    int n = 3;
    

    // One line(statement) with java 8 stream and list.subList

    List<List<Integer>> partitions = IntStream.range(0, list.size())
        .filter(i -> i % n == 0)
        .mapToObj(i -> list.subList(i, Math.min(i + n, list.size() )))
        .collect(Collectors.toList());
    
    0 讨论(0)
  • 2020-11-27 17:35
    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.List;
    
    public class SubListTest
    {
        public static void main(String[] args)
        {
            List<String> alphabetNames = new ArrayList<String>();
    
            // populate alphabetNames array with AAA,BBB,CCC,.....
            int a = (int) 'A';
            for (int i = 0; i < 26; i++)
            {
                char x = (char) (a + i);
                char[] array = new char[3];
                Arrays.fill(array, x);
                alphabetNames.add(new String(array));
            }
    
            int[] maxListSizes = new int[]
            {
                5, 10, 15, 20, 25, 30
            };
    
            for (int maxListSize : maxListSizes)
            {
                System.out.println("######################################################");
                System.out.println("Partitioning original list of size " + alphabetNames.size() + " in to sub lists of max size "
                    + maxListSize);
    
                ArrayList<List<String>> subListArray = new ArrayList<List<String>>();
                if (alphabetNames.size() <= maxListSize)
                {
                    subListArray.add(alphabetNames);
                }
                else
                {
                    // based on subLists of maxListSize X
                    int subListArraySize = (alphabetNames.size() + maxListSize - 1) / maxListSize;
                    for (int i = 0; i < subListArraySize; i++)
                    {
                        subListArray.add(alphabetNames.subList(i * maxListSize,
                            Math.min((i * maxListSize) + maxListSize, alphabetNames.size())));
                    }
                }
    
                System.out.println("Resulting number of partitions " + subListArray.size());
    
                for (List<String> subList : subListArray)
                {
                    System.out.println(subList);
                }
            }
        }
    }
    

    Output:

    ######################################################
    Partitioning original list of size 26 in to sub lists of max size 5
    Resulting number of partitions 6
    [AAA, BBB, CCC, DDD, EEE]
    [FFF, GGG, HHH, III, JJJ]
    [KKK, LLL, MMM, NNN, OOO]
    [PPP, QQQ, RRR, SSS, TTT]
    [UUU, VVV, WWW, XXX, YYY]
    [ZZZ]
    ######################################################
    Partitioning original list of size 26 in to sub lists of max size 10
    Resulting number of partitions 3
    [AAA, BBB, CCC, DDD, EEE, FFF, GGG, HHH, III, JJJ]
    [KKK, LLL, MMM, NNN, OOO, PPP, QQQ, RRR, SSS, TTT]
    [UUU, VVV, WWW, XXX, YYY, ZZZ]
    ######################################################
    Partitioning original list of size 26 in to sub lists of max size 15
    Resulting number of partitions 2
    [AAA, BBB, CCC, DDD, EEE, FFF, GGG, HHH, III, JJJ, KKK, LLL, MMM, NNN, OOO]
    [PPP, QQQ, RRR, SSS, TTT, UUU, VVV, WWW, XXX, YYY, ZZZ]
    ######################################################
    Partitioning original list of size 26 in to sub lists of max size 20
    Resulting number of partitions 2
    [AAA, BBB, CCC, DDD, EEE, FFF, GGG, HHH, III, JJJ, KKK, LLL, MMM, NNN, OOO, PPP, QQQ, RRR, SSS, TTT]
    [UUU, VVV, WWW, XXX, YYY, ZZZ]
    ######################################################
    Partitioning original list of size 26 in to sub lists of max size 25
    Resulting number of partitions 2
    [AAA, BBB, CCC, DDD, EEE, FFF, GGG, HHH, III, JJJ, KKK, LLL, MMM, NNN, OOO, PPP, QQQ, RRR, SSS, TTT, UUU, VVV, WWW, XXX, YYY]
    [ZZZ]
    ######################################################
    Partitioning original list of size 26 in to sub lists of max size 30
    Resulting number of partitions 1
    [AAA, BBB, CCC, DDD, EEE, FFF, GGG, HHH, III, JJJ, KKK, LLL, MMM, NNN, OOO, PPP, QQQ, RRR, SSS, TTT, UUU, VVV, WWW, XXX, YYY, ZZZ]
    
    0 讨论(0)
  • 2020-11-27 17:37

    One line using Java 8:

    IntStream.range(0, list.size() / batchSize + 1)
            .mapToObj(i -> list.subList(i * batchSize,
                    Math.min(i * batchSize + batchSize, list.size())))
            .filter(s -> !s.isEmpty()).collect(Collectors.toList());
    
    0 讨论(0)
  • 2020-11-27 17:40

    I just implemented a list partitioning, because I couldn't use a library.

    So I want to share my code here:

    import java.util.Iterator;
    import java.util.List;
    import java.util.NoSuchElementException;
    
    public class ListPartitioning<T> implements Iterable<List<T>> {
    
      private final List<T> list;
      private final int partitionSize;
    
      public ListPartitioning(List<T> list, int partitionSize) {
        if (list == null) {
          throw new IllegalArgumentException("list must not be null");
        }
        if (partitionSize < 1) {
          throw new IllegalArgumentException("partitionSize must be 1 or greater");
        }
        this.list = list;
        this.partitionSize = partitionSize;
      }
    
      @Override
      public Iterator<List<T>> iterator() {
        return new ListPartitionIterator<T>(list, partitionSize);
      }
    
      private static class ListPartitionIterator<T> implements Iterator<List<T>> {
    
        private int index = 0;
    
        private List<T> listToPartition;
        private int partitionSize;
        private List<T> nextPartition;
    
        public ListPartitionIterator(List<T> listToPartition, int partitionSize) {
          this.listToPartition = listToPartition;
          this.partitionSize = partitionSize;
        }
    
        @Override
        public boolean hasNext() {
          return index < listToPartition.size();
        }
    
        @Override
        public List<T> next() {
          if (!hasNext()) {
            throw new NoSuchElementException();
          }
    
          int partitionStart = index;
          int partitionEnd = Math.min(index + partitionSize, listToPartition.size());
    
          nextPartition = listToPartition.subList(partitionStart, partitionEnd);
          index = partitionEnd;
          return nextPartition;
        }
    
        @Override
        public void remove() {
          if (nextPartition == null) {
            throw new IllegalStateException("next must be called first");
          }
    
          nextPartition.clear();
          index -= partitionSize;
          nextPartition = null;
        }
      }
    }
    

    And the unit test based on testng.

    import org.testng.Assert;
    import org.testng.annotations.Test;
    
    import java.util.*;
    
    
    public class ListPartitioningTest {
    
      @Test(expectedExceptions = IllegalArgumentException.class)
      public void nullList() {
        ListPartitioning<String> lists = new ListPartitioning<String>(null, 1);
      }
    
      @Test(groups = Group.UNIT_TEST, expectedExceptions = IllegalArgumentException.class)
      public void wrongPartitionSize() {
        ListPartitioning<String> lists = new ListPartitioning<String>(new ArrayList<String>(), 0);
      }
    
    
      @Test()
      public void iteratorTest() {
        List<Integer> integers = Arrays.asList(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15);
        ListPartitioning<Integer> listPartitioning = new ListPartitioning<Integer>(integers, 7);
        Iterator<List<Integer>> partitionIterator = listPartitioning.iterator();
        Assert.assertNotNull(partitionIterator);
    
        Assert.assertTrue(partitionIterator.hasNext(), "next partition (first)");
        List<Integer> partition = partitionIterator.next();
        Assert.assertEquals(partition, Arrays.asList(0, 1, 2, 3, 4, 5, 6));
    
        Assert.assertTrue(partitionIterator.hasNext(), "next partition (second)");
        partition = partitionIterator.next();
        Assert.assertEquals(partition, Arrays.asList(7, 8, 9, 10, 11, 12, 13));
    
        Assert.assertTrue(partitionIterator.hasNext(), "next partition (third)");
        partition = partitionIterator.next();
        Assert.assertEquals(partition, Arrays.asList(14, 15));
    
        Assert.assertFalse(partitionIterator.hasNext());
      }
    
      @Test(expectedExceptions = NoSuchElementException.class)
      public void noSuchElementException() {
        List<Integer> integers = Arrays.asList(1);
        ListPartitioning<Integer> listPartitioning = new ListPartitioning<Integer>(integers, 2);
        Iterator<List<Integer>> partitionIterator = listPartitioning.iterator();
        List<Integer> partition = partitionIterator.next();
        partition = partitionIterator.next();
      }
    
      @Test(expectedExceptions = IllegalStateException.class)
      public void removeWithoutNext() {
        List<Integer> integers = new ArrayList<Integer>(Arrays.asList(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15));
        ListPartitioning<Integer> listPartitioning = new ListPartitioning<Integer>(integers, 7);
        Iterator<List<Integer>> partitionIterator = listPartitioning.iterator();
        partitionIterator.remove();
      }
    
      @Test()
      public void remove() {
        List<Integer> integers = new ArrayList<Integer>(Arrays.asList(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15));
        ListPartitioning<Integer> listPartitioning = new ListPartitioning<Integer>(integers, 7);
        Iterator<List<Integer>> partitionIterator = listPartitioning.iterator();
    
        partitionIterator.next();
        partitionIterator.next();
    
        partitionIterator.remove();
        Assert.assertTrue(partitionIterator.hasNext(), "next partition ");
        List<Integer> partition = partitionIterator.next();
        Assert.assertEquals(partition, Arrays.asList(14, 15));
    
        Assert.assertFalse(partitionIterator.hasNext());
    
        Assert.assertEquals(integers, Arrays.asList(0, 1, 2, 3, 4, 5, 6, 14, 15));
      }
    }
    
    0 讨论(0)
  • 2020-11-27 17:40

    What about

    Arrays.copyOfRange( original, from, to )
    

    ?

    0 讨论(0)
提交回复
热议问题