Efficient way to divide a list into lists of n size

前端 未结 14 1195
无人共我
无人共我 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:15

    If you are working with a list I use the "Apache Commons Collections 4" library. It has a partition method in the ListUtils class:

    ...
    int targetSize = 100;
    List<Integer> largeList = ...
    List<List<Integer>> output = ListUtils.partition(largeList, targetSize);
    

    This method is adapted from http://code.google.com/p/guava-libraries/

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

    Well i wrote one myself before i saw ColinD's answer (+1) and using Guava is definitely the way to go. It was too much fun to leave alone and so the below gives you a copy of the list rather than views so GUava's is definitely more efficient than this. I'm posting this because it was fun to write rather than suggesting it is as efficient:

    The Hamcrest test (one of anyway):

    assertThat(chunk(asList("a", "b", "c", "d", "e"), 2), 
               equalTo(asList(asList("a", "b"), asList("c", "d"), asList("e"))));
    

    The code:

    public static <T> Iterable<Iterable<T>> chunk(Iterable<T> in, int size) {
        List<Iterable<T>> lists = new ArrayList();
        Iterator<T> i = in.iterator();
        while (i.hasNext()) {
            List<T> list = new ArrayList();
            for (int j=0; i.hasNext() && j<size; j++) {
                list.add(i.next());
            }
            lists.add(list);
        }
        return lists;
    }
    
    0 讨论(0)
  • 2020-11-27 17:17

    For example:

        int partitionSize = 10;
        List<List<String>> partitions = new ArrayList<>();
    
        for (int i=0; i<yourlist.size(); i += partitionSize) {
            partitions.add(yourlist.subList(i, Math.min(i + partitionSize, yourlist.size())));
        }
    
        for (List<String> list : partitions) {
            //Do your stuff on each sub list
        }
    
    0 讨论(0)
  • 2020-11-27 17:17

    If you don't want to use a library, here's my solution

    1.To partition in N equal parts:

    private <T> List<List<T>> nPartition(List<T> objs, final int N) {
        return new ArrayList<>(IntStream.range(0, objs.size()).boxed().collect(
                Collectors.groupingBy(e->e%N,Collectors.mapping(e->objs.get(e), Collectors.toList())
                        )).values());
    }
    

    2. To partition in sets of N items:

    private <T> List<List<T>> nPartition(List<T> objs, final int N) {
        return new ArrayList<>(IntStream.range(0, objs.size()).boxed().collect(
                Collectors.groupingBy(e->e/N,Collectors.mapping(e->objs.get(e), Collectors.toList())
                        )).values());
        }
    

    In action here: https://ideone.com/QiQnbE

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

    Since you want to optimise your performance you should use a parallel stream instead of a for loop. This way you can use multiple threads.

    Lists.partition(A, n).parallelStream().forEach({
        //do stuff with temp
    });
    

    You can also use other ways to wort with the stream for example collect or map if it matches your purpose.

    0 讨论(0)
  • 2020-11-27 17:21
    public <E> Iterable<List<E>> partition(List<E> list, final int batchSize)
    {
        assert(batchSize > 0);
        assert(list != null);
        assert(list.size() + batchSize <= Integer.MAX_VALUE); //avoid overflow
    
        int idx = 0;
    
        List<List<E>> result = new ArrayList<List<E>>();
    
        for (idx = 0; idx + batchSize <= list.size(); idx += batchSize) {
            result.add(list.subList(idx, idx + batchSize));
        }
        if (idx < list.size()) {
            result.add(list.subList(idx, list.size()));
        }
    
        return result;
    }
    
    0 讨论(0)
提交回复
热议问题