Library method to partition a collection by a predicate
Use Guava's Multimaps.index
.
Here is an example, which partitions a list of words into two parts: those which have length > 3 and those that don't.
List<String> words = Arrays.asList("foo", "bar", "hello", "world");
ImmutableListMultimap<Boolean, String> partitionedMap = Multimaps.index(words, new Function<String, Boolean>(){
@Override
public Boolean apply(String input) {
return input.length() > 3;
}
});
System.out.println(partitionedMap);
prints:
false=[foo, bar], true=[hello, world]
If you're using Eclipse Collections (formerly GS Collections), you can use the partition
method on all RichIterables
.
MutableList<Integer> integers = FastList.newListWith(-3, -2, -1, 0, 1, 2, 3);
PartitionMutableList<Integer> result = integers.partition(IntegerPredicates.isEven());
Assert.assertEquals(FastList.newListWith(-2, 0, 2), result.getSelected());
Assert.assertEquals(FastList.newListWith(-3, -1, 1, 3), result.getRejected());
The reason for using a custom type, PartitionMutableList
, instead of Pair
is to allow covariant return types for getSelected() and getRejected(). For example, partitioning a MutableCollection
gives two collections instead of lists.
MutableCollection<Integer> integers = ...;
PartitionMutableCollection<Integer> result = integers.partition(IntegerPredicates.isEven());
MutableCollection<Integer> selected = result.getSelected();
If your collection isn't a RichIterable
, you can still use the static utility in Eclipse Collections.
PartitionIterable<Integer> partitionIterable = Iterate.partition(integers, IntegerPredicates.isEven());
PartitionMutableList<Integer> partitionList = ListIterate.partition(integers, IntegerPredicates.isEven());
Note: I am a committer for Eclipse Collections.
With the new java 8 features(stream and lambda epressions), you could write:
List<String> words = Arrays.asList("foo", "bar", "hello", "world");
Map<Boolean, List<String>> partitionedMap =
words.stream().collect(
Collectors.partitioningBy(word -> word.length() > 3));
System.out.println(partitionedMap);