What is the best way to filter a Java Collection?

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

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

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

    The setup:

    public interface Predicate<T> {
      public boolean filter(T t);
    }
    
    void filterCollection(Collection<T> col, Predicate<T> predicate) {
      for (Iterator i = col.iterator(); i.hasNext();) {
        T obj = i.next();
        if (predicate.filter(obj)) {
          i.remove();
        }
      }
    }
    

    The usage:

    List<MyObject> myList = ...;
    filterCollection(myList, new Predicate<MyObject>() {
      public boolean filter(MyObject obj) {
        return obj.shouldFilter();
      }
    });
    
    0 讨论(0)
  • 2020-11-21 07:36

    In Java 8, You can directly use this filter method and then do that.

     List<String> lines = Arrays.asList("java", "pramod", "example");
    
     List<String> result = lines.stream()              
             .filter(line -> !"pramod".equals(line))     
             .collect(Collectors.toList());              
    
     result.forEach(System.out::println); 
    
    0 讨论(0)
  • 2020-11-21 07:37

    Java 8 (2014) solves this problem using streams and lambdas in one line of code:

    List<Person> beerDrinkers = persons.stream()
        .filter(p -> p.getAge() > 16).collect(Collectors.toList());
    

    Here's a tutorial.

    Use Collection#removeIf to modify the collection in place. (Notice: In this case, the predicate will remove objects who satisfy the predicate):

    persons.removeIf(p -> p.getAge() <= 16);
    

    lambdaj allows filtering collections without writing loops or inner classes:

    List<Person> beerDrinkers = select(persons, having(on(Person.class).getAge(),
        greaterThan(16)));
    

    Can you imagine something more readable?

    Disclaimer: I am a contributor on lambdaj

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

    With Guava:

    Collection<Integer> collection = Lists.newArrayList(1, 2, 3, 4, 5);
    
    Iterators.removeIf(collection.iterator(), new Predicate<Integer>() {
        @Override
        public boolean apply(Integer i) {
            return i % 2 == 0;
        }
    });
    
    System.out.println(collection); // Prints 1, 3, 5
    
    0 讨论(0)
  • 2020-11-21 07:38

    Some really great great answers here. Me, I'd like to keep thins as simple and readable as possible:

    public abstract class AbstractFilter<T> {
    
        /**
         * Method that returns whether an item is to be included or not.
         * @param item an item from the given collection.
         * @return true if this item is to be included in the collection, false in case it has to be removed.
         */
        protected abstract boolean excludeItem(T item);
    
        public void filter(Collection<T> collection) {
            if (CollectionUtils.isNotEmpty(collection)) {
                Iterator<T> iterator = collection.iterator();
                while (iterator.hasNext()) {
                    if (excludeItem(iterator.next())) {
                        iterator.remove();
                    }
                }
            }
        }
    }
    
    0 讨论(0)
  • 2020-11-21 07:39

    I'll throw RxJava in the ring, which is also available on Android. RxJava might not always be the best option, but it will give you more flexibility if you wish add more transformations on your collection or handle errors while filtering.

    Observable.from(Arrays.asList(1, 2, 3, 4, 5))
        .filter(new Func1<Integer, Boolean>() {
            public Boolean call(Integer i) {
                return i % 2 != 0;
            }
        })
        .subscribe(new Action1<Integer>() {
            public void call(Integer i) {
                System.out.println(i);
            }
        });
    

    Output:

    1
    3
    5
    

    More details on RxJava's filter can be found here.

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