使用对象字段过滤 ArrayList

24

我有一个 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字段对我的List进行过滤,并且为了测试,我使用了字符串"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")));

但是这段代码没有起作用。


1
它为什么不工作?我敢打赌是编译错误... - fge
@fge 因为我正在使用一个字符串进行过滤,所以我需要使用对象的字段进行过滤,但我不知道该怎么做。 - Aimad Majdou
你需要实现自己的 Predicate,除了 notNull()/isNull() 之外,Predicates 提供的任何内容都无法以有意义的方式过滤你的对象。你读过 Functional explained 吗? - Frank Pavageau
1
我对Guava库不够熟悉,但我认为你需要使用Predicate.compose(Predicate<B> predicate, Function<A,? extends B> function)来创建一个新的函数,以测试特定字段是否正确。我会在几分钟内发布一个答案,提供确切的解决方案。但据我所知,这就是你应该做的。 - user1732480
7个回答

40

在Java 8中,使用过滤器

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

不使用lambda表达式将非常感激 :) - LOG_TAG

18

这是正常的:Predicates.containsPattern()CharSequence 上操作,而你的 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已经进行了演示。


这里的Lists是什么? - Lahiru Prasanna
@LahiruPrasanna 这是Guava的Lists,因为问题是关于Guava的。 - fge

15

你可以使用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);
}
}

3

使用Guava库,最简单的方法是使用Collections2.filter,示例如下:

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

3

Guava是一个库,它允许您在Java中使用一些函数式编程。

函数式编程中的一个优点是集合转换,例如:

Collection -> op -> op -> op -> transformedCollection。

看这里:

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

1
这并不复杂,只是被混淆了。 - Glenn Maynard

0

试试这个:

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

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


0
Try This : 
// For new filter list
val filtered: ArrayList<Article> = ArrayList<Article>()

//mainList is original list from which filter out items basis on condition
// use startswith/contains etc as per requirement
// below "query" used for search text related

mainList.filter{(it.desArt.lowercase().startsWith(query.lowercase())) }
.onEach { it1-> filtered.add(it1) }

1
你的回答可以通过提供更多支持性信息来改进。请编辑以添加进一步的细节,例如引用或文档,以便他人能够确认你的回答是否正确。你可以在帮助中心找到关于如何撰写好回答的更多信息。 - Diego Borba

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接