What is the best way to filter a Java Collection?

后端 未结 27 3088
故里飘歌
故里飘歌 2020-11-21 06:55

I want to filter a java.util.Collection based on a predicate.

相关标签:
27条回答
  • 2020-11-21 07:16

    The Collections2.filter(Collection,Predicate) method in Google's Guava library does just what you're looking for.

    0 讨论(0)
  • 2020-11-21 07:16

    Use Collection Query Engine (CQEngine). It is by far the fastest way to do this.

    See also: How do you query object collections in Java (Criteria/SQL-like)?

    0 讨论(0)
  • 2020-11-21 07:17

    Wait for Java 8:

    List<Person> olderThan30 = 
      //Create a Stream from the personList
      personList.stream().
      //filter the element to select only those with age >= 30
      filter(p -> p.age >= 30).
      //put those filtered elements into a new List.
      collect(Collectors.toList());
    
    0 讨论(0)
  • 2020-11-21 07:20

    This, combined with the lack of real closures, is my biggest gripe for Java. Honestly, most of the methods mentioned above are pretty easy to read and REALLY efficient; however, after spending time with .Net, Erlang, etc... list comprehension integrated at the language level makes everything so much cleaner. Without additions at the language level, Java just cant be as clean as many other languages in this area.

    If performance is a huge concern, Google collections is the way to go (or write your own simple predicate utility). Lambdaj syntax is more readable for some people, but it is not quite as efficient.

    And then there is a library I wrote. I will ignore any questions in regard to its efficiency (yea, its that bad)...... Yes, i know its clearly reflection based, and no I don't actually use it, but it does work:

    LinkedList<Person> list = ......
    LinkedList<Person> filtered = 
               Query.from(list).where(Condition.ensure("age", Op.GTE, 21));
    

    OR

    LinkedList<Person> list = ....
    LinkedList<Person> filtered = Query.from(list).where("x => x.age >= 21");
    
    0 讨论(0)
  • 2020-11-21 07:21

    "Best" way is too wide a request. Is it "shortest"? "Fastest"? "Readable"? Filter in place or into another collection?

    Simplest (but not most readable) way is to iterate it and use Iterator.remove() method:

    Iterator<Foo> it = col.iterator();
    while( it.hasNext() ) {
      Foo foo = it.next();
      if( !condition(foo) ) it.remove();
    }
    

    Now, to make it more readable, you can wrap it into a utility method. Then invent a IPredicate interface, create an anonymous implementation of that interface and do something like:

    CollectionUtils.filterInPlace(col,
      new IPredicate<Foo>(){
        public boolean keepIt(Foo foo) {
          return foo.isBar();
        }
      });
    

    where filterInPlace() iterate the collection and calls Predicate.keepIt() to learn if the instance to be kept in the collection.

    I don't really see a justification for bringing in a third-party library just for this task.

    0 讨论(0)
  • 2020-11-21 07:21

    My answer builds on that from Kevin Wong, here as a one-liner using CollectionUtils from spring and a Java 8 lambda expression.

    CollectionUtils.filter(list, p -> ((Person) p).getAge() > 16);
    

    This is as concise and readable as any alternative I have seen (without using aspect-based libraries)

    Spring CollectionUtils is available from spring version 4.0.2.RELEASE, and remember you need JDK 1.8 and language level 8+.

    0 讨论(0)
提交回复
热议问题