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);