我有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
的Person personid
作为键,将Person
对象作为值。因此,我只能遍历listOfIDs
并检查contains()
还有其他办法吗?
答案 0 :(得分:1)
如果列表变长,嵌套循环的实现将无法很好地扩展。您将要执行的操作数量是两个列表长度的乘积。
如果您的列表中至少有一个按ID排序,则可以使用二进制搜索。这将是对嵌套循环的改进。
构建Map
是一个好主意,并且可以很好地扩展。使用此技术,您将遍历Persons列表一次以构建映射,然后迭代ID列表一次以执行查找。确保使用人数初始化HashMap的大小(因此您不必在将人员放入Map中时重新进行重新散列)。这是一个非常可扩展的选项,不需要对任何列表进行排序。
如果BOTH列表碰巧按ID排序,那么您还有另一个有吸引力的选择:共同走下两个列表。您将从两个列表的开头开始,并在具有最小ID的列表中前进。如果ID相等,那么您执行业务逻辑以找到具有该ID的人员并在两个列表中前进。一旦你到达任何一个列表的末尾,你就完成了。
答案 1 :(得分:0)
Java的Collections
提供了一个非常快速的二进制搜索,但它假设您正在搜索列表的成员。您可以使用您的ID标准实现自己的:
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)) {
...
}