Фильтрация списка JavaBeans с помощью Google Guava

В программе на Java у меня есть список бобов, которые я хочу отфильтровать на основе определенного свойства.

Например, у меня есть список Person, JavaBean, где Person имеет много свойств, среди которых 'name'.

У меня также есть список имен.

Теперь я хочу найти всех людей, чье имя находится в списке имен.

Как лучше всего выполнить этот фильтр с помощью Google Guava?

До сих пор я думал об объединении Guava с Apache beanutils, но это не кажется элегантным.

Я также нашел библиотеку расширения отражения здесь: http://code.google.com/p/guava-reflection/, но я не уверен, как ее использовать (там мало документации).

Есть мысли?

p.s. Можете сказать, что мне очень не хватает понимания списков в Python?

23
задан Or Peles 26 December 2011 в 14:12
поделиться

5 ответов

Делай это по старинке, без гуавы. (Выступая в качестве разработчика на Guava.)

List<Person> filtered = Lists.newArrayList();
for(Person p : allPersons) {
   if(acceptedNames.contains(p.getName())) {
       filtered.add(p);
   }
}

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

42
ответ дан 29 November 2019 в 00:50
поделиться

Объясняя свои сомнения из предложения:

До сих пор я думал о комбинировании гуавы с beanutils Apache, но это не выглядит элегантно.

Java, несмотря на свою популярность, не обладает первоклассной функцией , поддержкой * , что может быть изменено в Java 8 , где вы сможете сделать:

Iterable <Person> filtered = filter(allPersons, (Person p) -> acceptedNames.contains(p.getName()));

С лямбдами, и это будет элегантно.

До этого у вас есть выбор между:

  • старой школой (как писал @Louis)
  • подробный фильтр гуавы (ответ @ JB)
  • или другие функциональные библиотеки Java (ответ @ superfav).

Я также хотел бы добавить к ответу @ Lois, что Guava-way будет создавать неизменную коллекцию , потому что они лучше, чем неизменяемые , который также описан в , пункт 15, Минимизировать изменчивость в Эффективная Java , Джошуа Блох ** :

ImmutableList.Builder<Person> builder = ImmutableList.builder();
for (final Person p : allPersons) {
    if (acceptedNames.contains(p.getName())) {
        builder.add(p);
    }
}
ImmutableList<Person> filtered = builder.build();

(Это реализация подробно, что ImmutableList.Builder создает временный ArrayList под капотом).

*: меня это очень беспокоит, я пришел из миров Python, JavaScript и Perl, , где функции обрабатываются лучше

**: Гуава и Блох тесно связаны во многих отношениях;)

5
ответ дан 29 November 2019 в 00:50
поделиться

Говоря как разработчик guava-рефлексии, я сожалею, что отказался от этого проекта на столь ранней стадии (у меня есть дневная работа и жена и дети :-)). Мое видение было примерно таким:

Iterable<Object> thingsWithNames = 
    Iterables.filter(someData,
                     // this is a Predicate, obviously
                     BeanProperties.hasBeanProperty("name", String.class));

Существующий код составляет около 60%, поэтому, если вам интересно, свяжитесь со мной, и, возможно, мы сможем закончить это вместе.

2
ответ дан 29 November 2019 в 00:50
поделиться

В стиле Java8 вы можете использовать стрим + фильтр для достижения своей цели.

persons.stream()
            .filter(p -> names.contains(p.getName()))
            .collect(Collectors.toList());
0
ответ дан 29 November 2019 в 00:50
поделиться

Вот пример использования обобщений с использованием guava, beanutils для фильтрации любого списка с использованием запрошенного совпадения

/**
 * Filter List
 * 
 * @param inputList
 * @param requestMatch
 * @param invokeMethod
 * @return
 */
public static <T> Iterable<T> predicateFilterList(List<T> inputList, final String requestMatch,
        final String invokeMethod) {
    Predicate<T> filtered = new Predicate<T>() {
        @Override
        public boolean apply(T input) {
            boolean ok = false;
            try {
                ok = BeanUtils.getProperty(input, invokeMethod).equalsIgnoreCase(requestMatch);
            }
            catch (Exception e) {
                e.printStackTrace();
            }
            return ok;
        }
    };
    return Iterables.filter(inputList, filtered);
}
0
ответ дан 29 November 2019 в 00:50
поделиться
Другие вопросы по тегам:

Похожие вопросы: