使用Google Guava过滤JavaBeans列表

Or *_*les 23 java functional-programming guava

在Java程序中,我有一个我想根据特定属性过滤的bean列表.

例如,假设我有一个Person列表,一个JavaBean,其中Person有许多属性,其中包括'name'.

我还有一个名单.

现在我想找到名字列在名单中的所有人.

使用Google Guava执行此过滤器的最佳方法是什么?

到目前为止,我已经考虑过将Guava与Apache beanutils相结合,但这似乎并不优雅.

我还在这里找到了一个反射扩展库:http://code.google.com/p/guava-reflection/,但我不确定如何使用它(这里有很少的文档).

有什么想法吗?

ps你能告诉我真的很想念Python列表理解吗?

Lou*_*man 42

没有番石榴,这是老式的做法.(作为番石榴开发者发言.)

List<Person> filtered = Lists.newArrayList();
for(Person p : allPersons) {
   if(acceptedNames.contains(p.getName())) {
       filtered.add(p);
   }
}
Run Code Online (Sandbox Code Playgroud)

你可以用Guava做到这一点,但Java不是Python,并试图将它变成Python只会使尴尬和难以理解的代码永久存在.Guava的功能性实用程序应该谨慎使用,并且只有当它们为代码行或性能提供具体且可衡量的好处时才应使用.

  • 您似乎认为妥协的唯一两个方面是可读性和性能.正确性比(假设的)可读性和性能更重要.如果这样做,您不仅要测试谓词逻辑,还要测试过滤逻辑.你不必要地加倍(至少,因为引入了可变状态)可能出错的事情的数量.将此乘以您在代码库中进行过滤的次数...为什么要以这种方式工作? (3认同)
  • 我同意你应该尽量减少_exposure_的可变性.返回ArrayList的ImmutableList副本,而不是ArrayList本身.但作为代码审查员,我更喜欢阅读此代码而不是其他代码.代码的显着部分更容易识别.如果这段代码返回了一个ImmutableList,我会对一两个测试以及谓词测试感到满意. (2认同)

JB *_*zet 23

Iterable<Person> filtered = Iterables.filter(allPersons, new Predicate<Person>() {
    @Override
    public boolean apply(Person p) {
        return acceptedNames.contains(p.getName());
    }
});
Run Code Online (Sandbox Code Playgroud)

如果您的名称列表很大,您最好将其转换为Set(HashSet,首选)并在此集合上调用contains,而不是列表,因为对于HashSet包含O(1),并且O(n)列表.


Xae*_*ess 5

从句子中解释你的怀疑:

到目前为止,我已经考虑过将Guava与Apache beanutils相结合,但这似乎并不优雅.

Java虽然如此受欢迎,但缺乏一流的功能支持*,Java 8中的变化,您将能够做到:

Iterable <Person> filtered = filter(allPersons, (Person p) -> acceptedNames.contains(p.getName()));
Run Code Online (Sandbox Code Playgroud)

有了lambdas,它会很优雅.

在此之前,您可以选择:

  • 老派的方式(像@Louis写的那样)
  • 详细的番石榴过滤器(@ JB的答案)
  • 或其他功能性Java库(@ superfav的答案).

我还想补充@ Lois的答案,即Guava-way将创建不可变集合,因为它们比不可修改更好,这也在第15项中描述,最小化 Joshua Bloch 中的有效Java中可变性**:

ImmutableList.Builder<Person> builder = ImmutableList.builder();
for (final Person p : allPersons) {
    if (acceptedNames.contains(p.getName())) {
        builder.add(p);
    }
}
ImmutableList<Person> filtered = builder.build();
Run Code Online (Sandbox Code Playgroud)

(这是在引擎盖下ImmutableList.Builder创建临时的实现细节ArrayList).

*:它让我很烦恼,我来自Python,JavaScript和Perl世界,其中功能得到了更好的处理

**:Guava和Bloch 在很多方面紧密耦合 ;)