Как выполнить поиск в списке объектов Java
У меня есть список объектов, и список очень большой. Объект
class Sample {
String value1;
String value2;
String value3;
String value4;
String value5;
}
Теперь мне нужно найти конкретное значение объекта в списке. Скажем, если value3=='three'
мне нужно вернуть эти объекты (мой поиск не всегда основан на значении3)
Список
List<Sample> list = new ArrayList<Sample>();
Каков эффективный способ сделать это?
Спасибо.
Ответы
Ответ 1
Вы можете попробовать Коллекции сообщества Apache.
Существует класс CollectionUtils, который позволяет выбирать или фильтровать элементы по Predicate.
Ваш код будет выглядеть следующим образом:
Predicate condition = new Predicate() {
boolean evaluate(Object sample) {
return ((Sample)sample).value3.equals("three");
}
};
List result = CollectionUtils.select( list, condition );
Update:
В java8, используя Lambdas и StreamAPI, это должно быть:
List<Sample> result = list.stream()
.filter(item -> item.value3.equals("three"))
.collect(Collectors.toList());
гораздо приятнее!
Ответ 2
Использование Java 8
С Java 8 вы можете просто преобразовать свой список в stream, позволяющий вам написать:
import java.util.List;
import java.util.stream.Collectors;
List<Sample> list = new ArrayList<Sample>();
List<Sample> result = list.stream()
.filter(a -> Objects.equals(a.value3, "three"))
.collect(Collectors.toList());
Обратите внимание, что
-
a -> Objects.equals(a.value3, "three")
является выражением лямбда
-
result
- это List
с типом Sample
- Это очень быстро, без кастинга на каждой итерации
- Если ваша логика фильтра становится тяжелее, вы можете сделать
list.parallelStream()
вместо list.stream()
(прочитать это)
Apache Commons
Если вы не можете использовать Java 8, вы можете использовать Apache Commons библиотеку и написать:
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.Predicate;
Collection result = CollectionUtils.select(list, new Predicate() {
public boolean evaluate(Object a) {
return Objects.equals(((Sample) a).value3, "three");
}
});
// If you need the results as a typed array:
Sample[] resultTyped = (Sample[]) result.toArray(new Sample[result.size()]);
Обратите внимание, что:
- На каждой итерации есть листинг от
Object
до Sample
- Если вам нужно, чтобы ваши результаты были напечатаны как
Sample[]
, вам нужен дополнительный код (как показано в моем примере).
Бонус: хорошая статья в блоге, рассказывающая о том, как найти элемент в списке.
Ответ 3
Если вы всегда выполняете поиск на основе value3
, вы можете сохранить объекты на карте:
Map<String, List<Sample>> map = new HashMap <>();
Затем вы можете заполнить карту с помощью key = value3
и value = списка объектов Sample с тем же свойством value3
.
Затем вы можете запросить карту:
List<Sample> allSamplesWhereValue3IsDog = map.get("Dog");
Примечание. Если экземпляры 2 Sample
могут иметь одинаковый value3
, вы можете просто использовать Map<String, Sample>
.
Ответ 4
Модифицируйте этот список и добавьте список в образцы, попробуйте это
Псевдокод
Sample {
List<String> values;
List<String> getList() {
return values}
}
for(Sample s : list) {
if(s.getString.getList.contains("three") {
return s;
}
}
Ответ 5
Поскольку ваш список равен ArrayList
, можно предположить, что он несортирован. Следовательно, нет никакого способа поиска элемента, который быстрее, чем O (n).
Если это возможно, вы должны подумать об изменении своего списка в Set
(с HashSet
как реализация) с определенным Comparator
для вашего класса образца.
Другая возможность - использовать HashMap
. Вы можете добавить свои данные как Sample
(пожалуйста, запустите имена классов с прописной буквой) и используйте строку, которую вы хотите искать как ключ. Тогда вы можете просто использовать
Sample samp = myMap.get(myKey);
Если на ключ может быть несколько выборок, используйте Map<String, List<Sample>>
, в противном случае используйте Map<String, Sample>
. Если вы используете несколько ключей, вам нужно будет создать несколько карт, содержащих один и тот же набор данных. Как все они указывают на одни и те же объекты, пространство не должно быть проблемой.