5
\$\begingroup\$

I have seen this question asked a few times, but I do not entirely understand the solutions provided. Below is a bit of code I came up with for splitting up an arraylist into five parts. I have tested and changed the array size from 0 to 16 and it works fine.

I am sure there is a "better" way of doing this, so I would like to see what others think.

public static void main(String[] args)
{
    ArrayList<String> arrayList = new ArrayList<String>();
    arrayList.add("A");//1
    arrayList.add("B");//2
    arrayList.add("C");//3
    arrayList.add("D");//4
    arrayList.add("E");//5
    arrayList.add("F");//6
    arrayList.add("G");//7
    arrayList.add("H");//8
    arrayList.add("I");//9
    arrayList.add("J");//10
    arrayList.add("K");//11
    arrayList.add("L");//12
    arrayList.add("M");//13
    arrayList.add("N");//14
    arrayList.add("O");//15
    arrayList.add("P");//16
    arrayList.add("X");//17

    int i1 = (int) Math.ceil(arrayList.size()/5.0);

    List<String> sublist = new ArrayList<String>();
    int x=0;
    for(int p=0; p<i1; p++)
    {
        if(arrayList.size()>=(x+5))
        {
            sublist = new ArrayList<String>(arrayList.subList(x, x+5));
            x+=5;
        }
        else
            sublist = new ArrayList<String>(arrayList.subList(x, arrayList.size()));
        for(String slist : sublist)
        {
            System.out.println("i:"+slist);
        }
    }
}
\$\endgroup\$

migrated from stackoverflow.com Jun 28 '13 at 20:58

This question came from our site for professional and enthusiast programmers.

8
\$\begingroup\$

It seems like you are mixing up the number of segments and the number of elements per segment. In your example, both are the same, so the result is correct, but in other cases it will not be. For instance, i1 is created as the number of elements per segment, with the number of segments being hard-coded as 5.0. Then, in the loop, you treat i1 as the number of segments, while the number of elements per segment is hard-coded as 5. Mistakes like this will be easier to spot if you use properly named variables, like numSegments or segmentSize instead of i1 or integer constants.

Also:

  • no need to wrap the sublists into new ArrayList
  • you can just count by increments according to the number of elements per sublist instead of using two counters, for the current sublist and the offset
  • you could use a ternary ... ? ... : ... instead of that if/else

How about this:

public static void main(String[] args) {
    List<String> arrayList = new ArrayList<String>();
    for (int i = 0; i < 23; i++) {
        arrayList.add(String.valueOf(i));
    }

    int size = 5;
    for (int start = 0; start < arrayList.size(); start += size) {
        int end = Math.min(start + size, arrayList.size());
        List<String> sublist = arrayList.subList(start, end);
        System.out.println(sublist);
    }
}

Here, size is the number of elements in each sublist. So instead of counting the segment of the list and increasing a second counter by 5 each time, you can just increase the first counter by five in the third argument of the for loop. Also, you can use the result of subList directly, without passing it to a constructor first. And you can get rid of the if-else by using min to determine the end index.

Output:

[0, 1, 2, 3, 4]
[5, 6, 7, 8, 9]
[10, 11, 12, 13, 14]
[15, 16, 17, 18, 19]
[20, 21, 22]

If instead of sublists with 5 elements you wanted five sublists, then use this (same result for the given example, but different for other list sizes):

int size = (int) Math.ceil(arrayList.size() / 5.0);
\$\endgroup\$
  • \$\begingroup\$ How to split array list in to equal parts of we dont know the chunk size (5 in your case) but we know the number of parts we want to make. e.g. how to split above 23 items in to 4 parts (dont know how many items should go to each part). My real use case is to split big file in to number of files \$\endgroup\$ – user1191081 Jun 13 '14 at 11:51
  • \$\begingroup\$ @user1191081 Maybe I'm missing something, but you just divide? 23 items to 4 parts -> 23/4 == 5.something -> 6 parts, i.e. ceil(numItems/numParts). \$\endgroup\$ – tobias_k Jun 13 '14 at 11:53
  • \$\begingroup\$ Why the simultaneous downvote to all three answers? \$\endgroup\$ – tobias_k Apr 5 '18 at 7:46
3
\$\begingroup\$

You can use Java 8 Collectors.groupingBy(Function<T,K> classifier) to do a list partitioning. What it does it simply divides an input list (e.g. List<String>) and divides it to a collection of n-size lists (e.g. Collection<List<String>>). Take a look at following code:

import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

public class Partition {

    public static void main(String[] args) {
        final List<String> list = Arrays.asList("A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","X");

        final AtomicInteger counter = new AtomicInteger(0);
        final int size = 5;

        final Collection<List<String>> partitioned = list.stream()
                .collect(Collectors.groupingBy(it -> counter.getAndIncrement() / size))
                .values();

        partitioned.forEach(System.out::println);
    }
}

We starts with list containing 17 elements. Our goal is to divide this list into lists of size 5 at maximum, no matter how many elements input list contains. What we do is we group all elements using a key computed as counter / size, so it generates a map like:

{0=[A,B,C,D,E], 1=[F,G,H,I,J], 2=[K,L,M,N,O], 3=[P,X]}

We are only interested in values of this map, so calling Map.values() method returns:

[[A,B,C,D,E], [F,G,H,I,J], [K,L,M,N,O], [P,X]]

And you can display these lists one by one with partitioned.forEach(System.out::println)

[A, B, C, D, E]
[F, G, H, I, J]
[K, L, M, N, O]
[P, X]

I hope it helps.

\$\endgroup\$
  • \$\begingroup\$ Neat. But is Map.values() guaranteed to return those in sorted order? \$\endgroup\$ – tobias_k Mar 15 '18 at 10:31

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.