Фильтр java.util.Collection в Java - PullRequest
2 голосов
/ 30 сентября 2010

Я написал класс util для фильтрации элементов в java.util.Collection следующим образом:

public class Util{
  public static <T> void filter(Collection<T> l, Filter<T> filter) {
    Iterator<T> it= l.iterator();
    while(it.hasNext()) {
      if(!filter.match(it.next())) {
        it.remove();
      }
    }
  }
}

public interface Filter<T> {
  public boolean match(T o);
}

Вопросы:

  1. Считаете ли вы необходимым написать метод?
  2. Есть ли какие-либо улучшения в методе?

Ответы [ 7 ]

5 голосов
/ 30 сентября 2010

Вы должны разрешить любые Filter<? super T>, а не только Filter<T>.

Клиенты могут также захотеть иметь метод, который вместо этого возвращает новую коллекцию:

public static <T> Collection<T> filter(Collection<T> unfiltered, 
    Filter<? super T> filter)
4 голосов
/ 30 сентября 2010
  1. Нет. guava-библиотеки уже имеют эту функцию.См. Iterables.filter(iterableCollection, predicate), где Predicate реализует фильтрацию
1 голос
/ 30 сентября 2010

По вопросу 1 уже много библиотек коллекций.Фильтрация по экземпляру предлагается по общим коллекциям apache CollectionUtils и коллекциям Google Итерации .

1 голос
/ 30 сентября 2010

Считаете ли вы необходимым написать метод?

Если вы не возражаете против использования сторонней библиотеки, тогда нет.

Некоторые предложения для сторонних библиотек, которые предоставляют эту функциональность:

Возможно, вы захотите взглянуть на Функциональная Java , которая предоставляет filter, а также многие другие функции более высокого порядка, встречающиеся в истинно синих функциональных языках.

Пример:

List<Person> adults = filter(people, new F1<Person, Boolean>() {
  public Boolean f(Person p) {
    return p.getAge() > 18;
  }
});

Другой альтернативой является использование lambdaj - библиотеки с аналогичными целями, но гораздо более краткой, чем функциональная Java.Тем не менее, лямбдадж не охватывает столько места, сколько функциональная Java.

Пример:

List<Person> adults = filter(having(on(Person.class).getAge(), greaterThan(18)), people);
1 голос
/ 30 сентября 2010

выглядит хорошо - но мы не можем решить, нужно ли это писать (ОК, вы на самом деле написали это;))

Метод remove() не всегда реализуется, он помечен (необязательно) . Некоторые итераторы просто выбрасывают UnsupportedOperationException. Вы должны перехватить его или преобразовать в пользовательское исключение, сказав, что эта коллекция не может быть отфильтрована.

И тогда вы можете изменить сигнатуру метода на

public static <T> void filter(Iterable<T> i, Filter<T> filter)

потому что итераторы не ограничиваются коллекциями. С помощью этого служебного метода вы можете фильтровать каждый «контейнер», который содержит итератор, который позволяет удалять операции.

1 голос
/ 30 сентября 2010

Необходимость зависит от того, чего вы хотите достичь. Если вы можете использовать сторонние библиотеки, такие как Google Collections, то нет. Если он планируется разовый, то, вероятно, нет. Если вы планируете создавать разные фильтры, то да, похоже, это хороший способ сохранить модульность и целостность.

Одно предложение - вы, возможно, захотите вернуть коллекцию - таким образом, у вас есть возможность вернуть новую отфильтрованную коллекцию, а не изменять ее. Это может быть удобно, если вам нужно использовать его в параллельном контексте.

Вы также можете посмотреть ответы на этот похожий вопрос .

0 голосов
/ 30 сентября 2010

Я думаю, было бы неплохо иметь метод visit(T o), определенный в вашем Filter<T> интерфейсе. Таким образом, реализация фильтра может решить, какое действие предпринять с посещенным объектом при совпадении.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...