2012-05-02 2 views
2

У меня есть коллекция Predicates, скажем List<Predicate<File>>. Затем у меня есть один File, и мне нужно получить предикат (если есть), который соответствует файлу. Я думал о том, как использовать Iterables.find(), но, конечно же, он принимает Predicate, а не значение, которое нужно передать в Predicate. Я думал о реализации следующего, но не знаю, существует ли уже механизм.Найти подходящий предикат. Предикат предиката?

public static <T> Predicate<Predicate<? super T>> createInversePredicate(
     final T value) { 
    return new Predicate<Predicate<? super T>>() { 

     @Override 
     public boolean apply(Predicate<? super T> input) { 
      return input.apply(value); 
     } 
    }; 
} 

Это позволит мне сделать следующее:

private List<Predicate<File>> filters = ...; 

@Nullable 
Predicate<File> findMatching(File file){ 
    return Iterables.find(filters, createInversePredicate(file), null); 
} 

есть лучший способ?

ответ

3

Guava команда участник здесь.

Вот как я это сделаю. Нет лучшего способа.

+0

Он существует уже служебный метод, как «createInversePredicate»? Если нет, я должен предложить это как проблему? –

+0

Вы могли бы, но это не похоже на очень распространенный случай использования. –

3

Я хотел бы избежать сложностей создания «обратный» предиката, а просто использовать императивный код:

private List<Predicate<File>> filters = ...; 

@Nullable 
Predicate<File> findMatchingFilter(File file){ 
    for (Predicate<File> filter : filters) { 
     if (filter.apply(file)) { 
      return filter; 
     } 
    } 
    return null; 
} 

Это более простое, а следующий программисту не нужно будет принимать 1 минуту, чтобы понять это " обратный»сказуемое бизнес :)

+0

Я не согласен по двум причинам: 1) Я ненавижу повторный код, и это включает в себя повторение того, что существует в библиотеке. Это область, в которой может произойти ошибка. 2) В Гуаве существует множество методов, где я мог бы использовать это без необходимости добавлять код (фильтр, find, findOnly и т. Д.) –

+0

Я не говорю, что такой обратный Предикат всегда плохая идея (вот почему я вчера поднял ваш вопрос). Это имеет смысл, если вы повторно используете такой предикат несколько раз и/или по-разному (фильтр, find, findOnly и т. Д.). Но до тех пор я следовал принципу YAGNI и стремился к простоте. Раздел ссылок на функциональные идиомы в вики Guava также уместен: http://code.google.com/p/guava-libraries/wiki/FunctionalExplained –

+1

Точка взята, спасибо за комментарий. –

0

Java 8 пользователи могут сделать это:

Predicate<File> findMatching(File file) { 
    List<Predicate<File>> matchingFilters = filters.stream().filter(predicate -> predicate.test(file)).collect(Collectors.toList()); 
    return matchingFilters.isEmpty()? null : matchingFilters.get(0); 
} 

Здесь я предполагаю, что только один предикат будет соответствовать файлу.

Вы также можете использовать Optional<Predicate<File>> вместо @Nullable в Java 8.

Смежные вопросы