[COLLECTIONS-393] Added ListUtils.partition method, thanks to Chris Shayan for report and patch.

git-svn-id: https://svn.apache.org/repos/asf/commons/proper/collections/trunk@1374049 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Thomas Neidhart 2012-08-16 20:50:27 +00:00
parent a5c9272431
commit b5715ec19d
3 changed files with 102 additions and 6 deletions

View File

@ -22,6 +22,9 @@
<body>
<release version="4.0" date="TBA" description="Next release">
<action issue="COLLECTIONS-393" dev="tn" type="add" due-to="Chris Shayan">
Added "ListUtils#partition" method to split a List into consecutive sublists.
</action>
<action issue="COLLECTIONS-272" dev="tn" type="add" due-to="Chaitanya Mutyala">
Added serialization support for "FixedOrderComparator" and "TransformingComparator".
</action>

View File

@ -16,6 +16,7 @@
*/
package org.apache.commons.collections;
import java.util.AbstractList;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
@ -438,5 +439,73 @@ public class ListUtils {
}
return -1;
}
/**
* Returns consecutive {@link List#subList(int, int) sublists} of a
* list, each of the same size (the final list may be smaller). For example,
* partitioning a list containing {@code [a, b, c, d, e]} with a partition
* size of 3 yields {@code [[a, b, c], [d, e]]} -- an outer list containing
* two inner lists of three and two elements, all in the original order.
* <p>
* The outer list is unmodifiable, but reflects the latest state of the
* source list. The inner lists are sublist views of the original list,
* produced on demand using {@link List#subList(int, int)}, and are subject
* to all the usual caveats about modification as explained in that API.
* <p>
* Adapted from http://code.google.com/p/guava-libraries/
*
* @param <T> the element type
* @param list the list to return consecutive sublists of
* @param size the desired size of each sublist (the last may be smaller)
* @return a list of consecutive sublists
* @throws IllegalArgumentException if list is {@code null} or size is not strictly positive
*/
public static <T> List<List<T>> partition(List<T> list, int size) {
if (list == null) {
throw new IllegalArgumentException("List must not be null");
}
if (size <= 0) {
throw new IllegalArgumentException("Size must be greater than 0");
}
return new Partition<T>(list, size);
}
/**
* Provides a partition view on a {@link List}.
*/
private static class Partition<T> extends AbstractList<List<T>> {
private final List<T> list;
private final int size;
private Partition(List<T> list, int size) {
this.list = list;
this.size = size;
}
public List<T> get(int index) {
int listSize = size();
if (listSize < 0) {
throw new IllegalArgumentException("negative size: " + listSize);
}
if (index < 0) {
throw new IndexOutOfBoundsException("Index " + index + " must not be negative");
}
if (index >= listSize) {
throw new IndexOutOfBoundsException("Index " + index + " must be less than size " +
listSize);
}
int start = index * size;
int end = Math.min(start + size, list.size());
return list.subList(start, end);
}
public int size() {
return (list.size() + size - 1) / size;
}
@Override
public boolean isEmpty() {
return list.isEmpty();
}
}
}

View File

@ -22,6 +22,7 @@ import java.util.Collection;
import java.util.Collections;
import java.util.List;
import junit.framework.Assert;
import junit.framework.Test;
import org.apache.commons.collections.functors.EqualPredicate;
@ -30,12 +31,7 @@ import org.apache.commons.collections.list.PredicatedList;
/**
* Tests for ListUtils.
*
* @version $Revision$
*
* @author Stephen Colebourne
* @author Neil O'Toole
* @author Matthew Hawthorne
* @author Dave Meikle
* @version $Id$
*/
public class TestListUtils extends BulkTest {
@ -297,4 +293,32 @@ public class TestListUtils extends BulkTest {
assertEquals(ListUtils.indexOf(fullList, null), -1);
}
public void testPartition() {
List<Integer> strings = new ArrayList<Integer>();
for (int i = 0; i <= 6; i++) {
strings.add(i);
}
final List<List<Integer>> partition = ListUtils.partition(strings, 3);
assertNotNull(partition);
assertEquals(3, partition.size());
assertEquals(1, partition.get(2).size());
try {
ListUtils.partition(null, 3);
Assert.fail("failed to check for null argument");
} catch (IllegalArgumentException e) {}
try {
ListUtils.partition(strings, 0);
Assert.fail("failed to check for size argument");
} catch (IllegalArgumentException e) {}
try {
ListUtils.partition(strings, -10);
Assert.fail("failed to check for size argument");
} catch (IllegalArgumentException e) {}
}
}