3

I have a situation where we are passing a List to a method for processing. We need to now make sure that we only pass a list that has 40 items at any given time. In other words, if the list has 100 items, then it should invoke the method by passing the list with 40 items, then 40 again and then the last 20. How can I achieve this behavior? Some examples will be really helpful.

Aashi
  • 31
  • 2
  • 1
    Could you explain why do you have a 40 items limitation ? This would be very helpful to avoid reproducing the same problem in the solution – VirtualTroll Feb 22 '12 at 20:34
  • Appreciate all the help. The limitation is from another service that we are calling and that service method only handles 40 at a time and gives back error in the response if it is over 40. So in our code when the client request object contains this list with items over 40, I need to be able to break it up and call that transaction method multiple times by passing sublists if needed and then track each response. – Aashi Feb 23 '12 at 16:13

6 Answers6

4

Something like this should work without the overhead of generating a list of sublists:

void process(List<Thing> list) {
    final int len = list.size();
    if (len > 40) {
        int start = 0;
        do {
            final end = Math.min(len, start + 40);
            process(list.sublist(start, end));
            start = end;
        } while (start < len);
    } else {
        // process list of length <= 40 here
    }
}
Ted Hopp
  • 232,168
  • 48
  • 399
  • 521
  • 1
    To quote [@skaffman](http://stackoverflow.com/questions/1143951/what-is-the-simplest-way-to-convert-a-java-string-from-all-caps-words-separated#comment962057_1144050): _"No sir! We should rewrite these existing, already-working utilities ourselves, for we are proper programmers!"_ – Matt Ball Feb 22 '12 at 20:44
  • 2
    @MДΓΓБДLL - Not everyone Java project has Guava as a resource (see, e.g., the response to skaffman by [MДΓΓ БДLL](http://stackoverflow.com/questions/1143951/what-is-the-simplest-way-to-convert-a-java-string-from-all-caps-words-separated#comment980758_1144050); there's value in an answer that uses only the standard Java api. – Ted Hopp Feb 22 '12 at 20:58
2

With Guava, this is stupidly simple:

List<Foo> foos = /* whatever */;
for (List<Foo> part : Lists.partition(foos, 40))
{
    doSomethingWith(part);
}
Matt Ball
  • 354,903
  • 100
  • 647
  • 710
1

Guava's Lists.partition(List<E>, int) chunks a specified List into sublists of the specified size, which sounds exactly appropriate for your use case.

Louis Wasserman
  • 191,574
  • 25
  • 345
  • 413
1

Here is a pure Java example:

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

    for (int i = 0; i < (list.size()/40.0); i++) {
        maxForty(list.subList(i * 40, Math.min(((i + 1) * 40), list.size())));
    }
}

public static void maxForty(List<Integer> list) {
    System.out.println("List size: " + list.size());
}

Prints out:

List size: 40
List size: 40
List size: 20
B. Anderson
  • 3,079
  • 25
  • 33
0

Before you call your method, test the size of your list. If it's higher than 40 you can start a loop that will create a new List of 40 items (maximum) and pass that list as your method call parameter.

talnicolas
  • 13,885
  • 7
  • 36
  • 56
0

Google's Guava has a method Lists.partition, which takes a List and a partition size, and returns a List of Lists. As an example:

List<Foo> fooList = new ArrayList<Foo>();
//add 100 items to fooList
List<List<Foo>> partitionedFoos = Lists.partition(fooList, 40);
//A List containing 3 lists, the first two with 40 Foos, the last with 20.
for(List<Foo> foos : paritionedFoos){
    bar(foos);
}
TDJoe
  • 1,388
  • 1
  • 10
  • 15