通过谓词对集合进行分区的库方法

Edw*_*ale 28 java collections guava

我有一个对象集合,我想分成两个集合,其中一个传递一个谓词,其中一个未通过谓词.我希望有一个Guava方法可以做到这一点,但它们最接近的是过滤器,它不会给我另一个集合.

我想图像方法的签名将是这样的:

public static <E> Pair<Collection<E>, Collection<E>> partition(Collection<E> source, Predicate<? super E> predicate)
Run Code Online (Sandbox Code Playgroud)

我意识到这对我自己的编码速度非常快,但我正在寻找一种能够实现我想要的现有库方法.

dog*_*ane 26

使用番石榴Multimaps.index.

下面是一个示例,它将单词列表分为两部分:长度> 3的那些和不具有长度> 3的部分.

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);
Run Code Online (Sandbox Code Playgroud)

打印:

false=[foo, bar], true=[hello, world]
Run Code Online (Sandbox Code Playgroud)

  • 如果你已经有了一个谓词,你可以把它变成一个带有Functions.forPredicate的函数. (4认同)
  • 更新Java 8:流包中也提供了类似的方法`java.util.stream.Collectors #groupingBy(java.util.function.Function <....>)`它就像`words.stream() .collect(Collectors.groupingBy(FUNC))` (4认同)

gon*_*ard 12

使用新的java 8功能(lambda epressions),您可以编写:

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);
Run Code Online (Sandbox Code Playgroud)


Cra*_*lin 5

如果您使用Eclipse Collections(以前称为 GS Collections),则可以partition在所有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());
Run Code Online (Sandbox Code Playgroud)

使用自定义类型 的原因PartitionMutableListPair允许 getSelected() 和 getRejected() 的协变返回类型。例如,对 a 进行分区MutableCollection会得到两个集合而不是列表。

MutableCollection<Integer> integers = ...;
PartitionMutableCollection<Integer> result = integers.partition(IntegerPredicates.isEven());
MutableCollection<Integer> selected = result.getSelected();
Run Code Online (Sandbox Code Playgroud)

如果您的集合不是RichIterable,您仍然可以使用 Eclipse Collections 中的静态实用程序。

PartitionIterable<Integer> partitionIterable = Iterate.partition(integers, IntegerPredicates.isEven());
PartitionMutableList<Integer> partitionList = ListIterate.partition(integers, IntegerPredicates.isEven());
Run Code Online (Sandbox Code Playgroud)

注意:我是 Eclipse Collections 的提交者。