В программе на Java у меня есть список бобов, которые я хочу отфильтровать на основе определенного свойства.
Например, у меня есть список Person, JavaBean, где Person имеет много свойств, среди которых 'name'.
У меня также есть список имен.
Теперь я хочу найти всех людей, чье имя находится в списке имен.
Как лучше всего выполнить этот фильтр с помощью Google Guava?
До сих пор я думал об объединении Guava с Apache beanutils, но это не кажется элегантным.
Я также нашел библиотеку расширения отражения здесь: http://code.google.com/p/guava-reflection/, но я не уверен, как ее использовать (там мало документации).
Есть мысли?
p.s. Можете сказать, что мне очень не хватает понимания списков в Python?
Делай это по старинке, без гуавы. (Выступая в качестве разработчика на Guava.)
List<Person> filtered = Lists.newArrayList();
for(Person p : allPersons) {
if(acceptedNames.contains(p.getName())) {
filtered.add(p);
}
}
Вы можете сделать это с Guava, но Java не является Python, и попытка превратить его в Python просто увековечит неуклюжий и нечитаемый код. Функциональные утилиты Guava должны использоваться экономно, и только тогда, когда они обеспечивают конкретное и измеримое преимущество для строк кода или производительности.
Объясняя свои сомнения из предложения:
До сих пор я думал о комбинировании гуавы с beanutils Apache, но это не выглядит элегантно.
Java, несмотря на свою популярность, не обладает первоклассной функцией , поддержкой * sup>, что может быть изменено в Java 8 , где вы сможете сделать:
Iterable <Person> filtered = filter(allPersons, (Person p) -> acceptedNames.contains(p.getName()));
С лямбдами, и это будет элегантно.
До этого у вас есть выбор между:
Я также хотел бы добавить к ответу @ Lois, что Guava-way будет создавать неизменную коллекцию , потому что они лучше, чем неизменяемые , который также описан в , пункт 15, Минимизировать изменчивость в Эффективная Java , Джошуа Блох ** sup>:
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, , где функции обрабатываются лучше
**: Гуава и Блох тесно связаны во многих отношениях;)
Говоря как разработчик guava-рефлексии, я сожалею, что отказался от этого проекта на столь ранней стадии (у меня есть дневная работа и жена и дети :-)). Мое видение было примерно таким:
Iterable<Object> thingsWithNames =
Iterables.filter(someData,
// this is a Predicate, obviously
BeanProperties.hasBeanProperty("name", String.class));
Существующий код составляет около 60%, поэтому, если вам интересно, свяжитесь со мной, и, возможно, мы сможем закончить это вместе.
В стиле Java8 вы можете использовать стрим + фильтр для достижения своей цели.
persons.stream()
.filter(p -> names.contains(p.getName()))
.collect(Collectors.toList());
Вот пример использования обобщений с использованием 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);
}