У меня есть List<Person> persons = new ArrayList<Person>()
, размер этого списка 100+. Я хочу проверить, содержится ли в этом списке конкретный объект personID
. Сейчас я делаю это так:
for(Person person : persons)
{
for(Long pid : listOfIDs)
{
if(person.personid == pid)
{
// do somthing
}
else
{
// do somthing
}
} // end of inner for
}
Но я не хочу просматривать список persons
для каждого элемента в listOfIDs
. Я подумал о том, чтобы взять HashMap
человека с personid
в качестве ключа и объекта Person
в качестве значения. Так что я могу пройти только через listOfIDs
и проверить, нет ли contains()
Есть ли другой способ сделать это?
2 ответа
Ваша реализация с вложенными циклами не будет хорошо масштабироваться, если списки станут длинными. Количество операций, которые вы сделаете, будет произведением длины двух списков.
Если хотя бы один из ваших списков отсортирован по идентификатору, вы можете использовать двоичный поиск. Это будет улучшением по сравнению с вложенными циклами.
Создание Map
- хорошая идея, и она хорошо масштабируется. Используя этот метод, вы будете перебирать список лиц один раз, чтобы построить карту, а затем перебирать список идентификаторов один раз, чтобы выполнить поиск. Убедитесь, что вы инициализировали размер HashMap с количеством лиц (чтобы вам не приходилось повторно хешировать, когда вы помещаете людей в карту). Это очень масштабируемый вариант и не требует сортировки ни одного списка.
Если ОБА списков сортируются по идентификатору, у вас есть еще одна привлекательная альтернатива: вместе пройтись по двум спискам. Вы начнете с начала обоих списков и продвинетесь вперед по списку с наименьшим идентификатором. Если идентификаторы равны, то вы выполняете свою бизнес-логику для того, чтобы найти человека с этим идентификатором, и шагать вперед в обоих списках. Как только вы дойдете до конца любого списка, все готово.
Java Collections
обеспечивает очень быстрый двоичный поиск, но предполагает, что вы ищете элемент списка. Вы можете реализовать свой собственный, используя критерии идентификатора:
Collections.sort(persons, (p1, p2) -> p1.personID - p2.personID);
if (binarySearch(persons, id)) {
...
}
boolean binarySearch(List<Person> personList, Long id) {
if (personList.empty())
return false;
long indexToTest = personList.size() / 2;
long idToTest = personList.get(indexToTest).personID;
if (idToTest < id)
return binarySearch(personList.subList(indexToTest + 1, personList.size());
else if (idToTest > id)
return binarySearch(personList.subList(0, indexToTest));
else
return true;
}
Если вы не хотите сортировать свой список, вы можете скопировать его в отсортированный список и выполнить поиск по нему: для больших списков, которые все равно будут намного быстрее, чем повторение по нему. На самом деле это очень похоже на хранение отдельной хеш-карты (хотя хеш-карта могла бы быть быстрее).
Если вы должны выполнять итерацию, вы можете по крайней мере использовать параллельный поток, чтобы воспользоваться преимуществами нескольких ядер, если они у вас есть:
if (persons.parallelStream().anyMatch(p -> p.personID == id)) {
...
}
Похожие вопросы
Новые вопросы
java
Java — это высокоуровневый объектно-ориентированный язык программирования. Используйте этот тег, если у вас возникли проблемы с использованием или пониманием самого языка. Этот тег часто используется вместе с другими тегами для библиотек и/или фреймворков, используемых разработчиками Java.