[COLLECTIONS-450] Added CollectionUtils.forAllButLastDo(...) methods. Thanks to J. Moldawski

git-svn-id: https://svn.apache.org/repos/asf/commons/proper/collections/trunk@1475937 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Thomas Neidhart 2013-04-25 20:02:15 +00:00
parent f7c4d60cda
commit cb3b31ed23
3 changed files with 100 additions and 0 deletions

View File

@ -28,6 +28,10 @@
<action issue="COLLECTIONS-451" dev="tn" type="update"> <action issue="COLLECTIONS-451" dev="tn" type="update">
The constructors for all Utils classes are now private to prevent instantiation. The constructors for all Utils classes are now private to prevent instantiation.
</action> </action>
<action issue="COLLECTIONS-450" dev="tn" type="add" due-to="J. Moldawski">
Added methods "forAllButLastDo(Collection, Closure)" and "forAllButLastDo(Iterator, Closure)"
to class "CollectionUtils".
</action>
<action issue="COLLECTIONS-447" dev="tn" type="fix" due-to="Jeffrey Barnes"> <action issue="COLLECTIONS-447" dev="tn" type="fix" due-to="Jeffrey Barnes">
Tree traversal with a TreeListIterator will not be affected anymore by Tree traversal with a TreeListIterator will not be affected anymore by
the removal of an element directly after a call to previous(). the removal of an element directly after a call to previous().

View File

@ -694,6 +694,47 @@ public class CollectionUtils {
return closure; return closure;
} }
/**
* Executes the given closure on each but the last element in the collection.
* <p>
* If the input collection or closure is null, there is no change made.
*
* @param <T> the type of object the {@link Collection} contains
* @param <C> the closure type
* @param collection the collection to get the input from, may be null
* @param closure the closure to perform, may be null
* @return the last element in the collection, or null if either collection or closure is null
*/
public static <T, C extends Closure<? super T>> T forAllButLastDo(final Collection<T> collection,
final C closure) {
return collection != null && closure != null ? forAllButLastDo(collection.iterator(), closure) : null;
}
/**
* Executes the given closure on each but the last element in the collection.
* <p>
* If the input collection or closure is null, there is no change made.
*
* @param <T> the type of object the {@link Collection} contains
* @param <C> the closure type
* @param iterator the iterator to get the input from, may be null
* @param closure the closure to perform, may be null
* @return the last element in the collection, or null if either iterator or closure is null
*/
public static <T, C extends Closure<? super T>> T forAllButLastDo(final Iterator<T> iterator, final C closure) {
if (iterator != null && closure != null) {
while (iterator.hasNext()) {
final T element = iterator.next();
if (iterator.hasNext()) {
closure.execute(element);
} else {
return element;
}
}
}
return null;
}
/** /**
* Filter the collection by applying a Predicate to each element. If the * Filter the collection by applying a Predicate to each element. If the
* predicate returns false, remove the element. * predicate returns false, remove the element.

View File

@ -663,6 +663,61 @@ public class CollectionUtilsTest extends MockTestCase {
CollectionUtils.forAllDo(col, testClosure); CollectionUtils.forAllDo(col, testClosure);
} }
@Test
public void forAllButLastDoCollection() {
final Closure<List<? extends Number>> testClosure = ClosureUtils.invokerClosure("clear");
final Collection<List<? extends Number>> col = new ArrayList<List<? extends Number>>();
col.add(collectionA);
col.add(collectionB);
List<? extends Number> lastElement = CollectionUtils.forAllButLastDo(col, testClosure);
assertSame(lastElement, collectionB);
assertTrue(collectionA.isEmpty() && !collectionB.isEmpty());
col.clear();
col.add(collectionB);
lastElement = CollectionUtils.forAllButLastDo(col, testClosure);
assertSame(lastElement, collectionB);
assertTrue(!collectionB.isEmpty() );
col.clear();
lastElement = CollectionUtils.forAllButLastDo(col, testClosure);
assertNull(lastElement);
Collection<String> strings = Arrays.asList(new String[]{"a", "b", "c"});
final StringBuffer result = new StringBuffer();
result.append(CollectionUtils.forAllButLastDo(strings, new Closure<String>() {
public void execute(String input) {
result.append(input+";");
}
}));
assertEquals("a;b;c", result.toString());
Collection<String> oneString = Arrays.asList(new String[]{"a"});
final StringBuffer resultOne = new StringBuffer();
resultOne.append(CollectionUtils.forAllButLastDo(oneString, new Closure<String>() {
public void execute(String input) {
resultOne.append(input+";");
}
}));
assertEquals("a", resultOne.toString());
assertNull(CollectionUtils.forAllButLastDo(strings, null));
assertNull(CollectionUtils.forAllButLastDo((Collection<?>) null, null));
}
@Test
public void forAllButLastDoIterator() {
final Closure<List<? extends Number>> testClosure = ClosureUtils.invokerClosure("clear");
final Collection<List<? extends Number>> col = new ArrayList<List<? extends Number>>();
col.add(collectionA);
col.add(collectionB);
List<? extends Number> lastElement = CollectionUtils.forAllButLastDo(col.iterator(), testClosure);
assertSame(lastElement, collectionB);
assertTrue(collectionA.isEmpty() && !collectionB.isEmpty());
assertNull(CollectionUtils.forAllButLastDo(col.iterator(), null));
assertNull(CollectionUtils.forAllButLastDo((Collection<?>) null, null));
}
@Test @Test
public void getFromMap() { public void getFromMap() {
// Unordered map, entries exist // Unordered map, entries exist