使用对象的字段过滤 ArrayList

Posted

技术标签:

【中文标题】使用对象的字段过滤 ArrayList【英文标题】:filtering an ArrayList using an object's field 【发布时间】:2013-05-27 05:33:53 【问题描述】:

我有一个由对象填充的 ArrayList。

我的对象类名为Article,它有两个字段;

public class Article 

    private int codeArt;
    private String desArt;

  public Article(int aInt, String string) 
        this.desArt = string;
        this.codeArt = aInt;
    

    public int getCodeArt() return codeArt; 
    public void setCodeArt(int codeArt) this.codeArt = codeArt;
    public String getDesArt() return desArt;
    public void setDesArt(String desArt)  this.desArt = desArt;


我想使用desArt 字段过滤我的列表,而对于测试,我使用了字符串“test”。

我使用了谷歌的 Guava,它允许我过滤 ArrayList。

这是我尝试过的代码:

private List<gestionstock.Article> listArticles = new ArrayList<>();

//Here the I've filled my ArrayList

private List<gestionstock.Article> filteredList filteredList = Lists.newArrayList(Collections2.filter(listArticles, Predicates.containsPattern("test")));

但此代码不起作用。

【问题讨论】:

怎么不工作?我敢打赌编译错误... @fge 因为我正在使用字符串进行过滤,我没有使用对象的字段进行过滤,但我不知道该怎么做。 您需要实现自己的PredicatePredicates 提供的那些(notNull()/isNull() 除外)都无法以有意义的方式过滤您的对象。你读过Functional explained吗? 我对 Guava 库并不熟悉,但我认为您需要使用 Predicate.compose(Predicate predicate, Function function)创建一个新函数来测试特定字段是否正确。我将在几分钟内发布一个带有某种确切解决方案的答案。但据我了解,这是你应该做的。 【参考方案1】:

您可以使用 for 循环或 for each 循环遍历列表。 您想根据某些条件创建另一个列表吗? 我认为这应该可行。

List<Article> secondList = new ArrayList<Article>();

for( Article a : listArticles)  
// or equalsIgnoreCase or whatever your conditon is
if (a.getDesArt().equals("some String")) 
// do something 
secondList.add(a);


【讨论】:

【参考方案2】:

这是正常的:Predicates.containsPattern() 在 CharSequences 上运行,而您的 gestionStock.Article 对象没有实现。

您需要编写自己的谓词:

public final class ArticleFilter
    implements Predicate<gestionstock.Article>

    private final Pattern pattern;

    public ArticleFilter(final String regex)
    
        pattern = Pattern.compile(regex);
    

    @Override
    public boolean apply(final gestionstock.Article input)
    
        return pattern.matcher(input.getDesArt()).find();
    

然后使用:

 private List<gestionstock.Article> filteredList
     = Lists.newArrayList(Collections2.filter(listArticles,     
         new ArticleFilter("test")));

但是,正如@mgnyp 所展示的那样,这是相当多的代码,可以使用非函数式编程在更少的代码中完成......

【讨论】:

这里的列表是什么? @LahiruPrasanna 这是番石榴的Lists,因为问题是关于番石榴的【参考方案3】:

试试这个:

private List<gestionstock.Article> listArticles = new ArrayList<>();
private List<gestionstock.Article> filteredList filteredList = Lists.newArrayList(Collections2.filter(listArticles, new Predicate<gestionstock.Article>()
        public boolean apply(gestationstock.Article article)
            return article.getDesArt().contains("test")
        
    ));

这个想法是因为您使用的是自定义对象,所以您应该实现自己的谓词。如果您在其他任何地方使用它,请在文件中定义它,否则,此实现效果很好。

【讨论】:

【参考方案4】:

Guava 是一个库,可让您在 Java 中使用一些函数式编程。 函数式编程中最成功的事情之一是集合转换,例如

集合 -> 操作 -> 操作 -> 操作 -> 转换集合。

看这里:

Collection<Article> filtered = from(listArticles).filter(myPredicate1).filter(myPredicate2).filter(myPredicate3).toImmutableList();

很漂亮,不是吗?

第二个成功的事情是 lambda 函数。看这里:

Collection<Article> filtered = from(listArticles)
  .filter((Predicate) (candidate) ->  return candidate.getCodeArt() > SOME_VALUE )
  .toImmutableList();

实际上,Java 还没有纯 lambda 函数。我们将能够在 Java 8 中做到这一点。但现在我们可以在 IDE Inellij Idea 中编写此代码,并且 IDE 将此类 lambda 转换为 Predicate,即时创建:

Collection<Article> filtered = from(listArticles)
        .filter(new Predicate<Article>() 
            @Override
            public boolean apply(Article candidate) 
                return candidate.getCodeArt() > SOME_VALUE;
            
        )
        .toImmutableList();

如果您的过滤条件需要正则表达式,代码会变得更加复杂,您需要将条件移动到单独的方法或将整个 Predicate 移动到单独的类。

如果所有这些函数式编程看起来太复杂,只需创建新集合并手动填充它(不使用 Guava):

List<Article> filtered = new ArrayList<Article>();
for(Article article : listArticles)

    if(article.getCodeArt() > SOME_VALUE)
        filtered.add(article);

【讨论】:

并不复杂,只是被混淆了。【参考方案5】:

对于 Guava,我想说到目前为止最简单的方法是使用 Collections2.filter,例如:

Collections2.filter(YOUR_COLLECTION, new Predicate<YOUR_OBJECT>() 
  @Override
  public boolean apply(YOUR_OBJECT candidate) 
    return SOME_ATTRIBUTE.equals(candidate.getAttribute());
  
);

【讨论】:

【参考方案6】:

在 Java 8 中,使用过滤器

List<Article> articleList = new ArrayList<Article>();
List<Article> filteredArticleList= articleList.stream().filter(article -> article.getDesArt().contains("test")).collect(Collectors.toList());

【讨论】:

不使用lamda表达式将不胜感激:)

以上是关于使用对象的字段过滤 ArrayList的主要内容,如果未能解决你的问题,请参考以下文章

如何使用附加过滤的相关对象作为 Django 中的字段来获取结果?

JQ 过滤嵌套对象中的字段

如何使用 PHP 从 Google Clas-s-room 课程列表中过滤课程对象字段

Django-create 过滤器基于使用 Q 对象和 if elif 条件的每个字段

从返回域对象列表的 RESTful Web 服务端点的响应中动态过滤字段

Django如何过滤多对多字段中的对象,而不是原始查询集