[英]Fastest and optimized way to search for value in a List<T>
我有一個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
}
但是我不想遍歷listOfIDs
每個元素的persons
列表。 我想到將personid
的Person HashMap
作為鍵,並將Person
對象作為值。 這樣我只能遍歷listOfIDs
並檢查contains()
還有其他方法嗎?
如果列表過長,則使用嵌套循環的實現將無法很好地擴展。 您將要執行的操作數是兩個列表的長度的乘積。
如果您的列表中至少有一個按ID排序,則可以使用二進制搜索。 這將是對嵌套循環的改進。
制作Map
是個好主意,並且可以很好地擴展。 使用此技術,您將遍歷“人員”列表一次以構建地圖,然后遍歷“ ID”列表一次以進行查找。 確保使用Persons的數量初始化HashMap的大小(這樣,在將Persons放入Map中時不必重新哈希)。 這是一個非常可擴展的選項,不需要對任何一個列表進行排序。
如果兩個列表碰巧都按ID排序,那么您還有另一種有吸引力的選擇:一起沿着兩個列表走。 您將從兩個列表的開頭開始,然后在ID最小的列表中向前移動。 如果這些ID相等,則您要執行業務邏輯以找到具有該ID的人並在兩個列表中都向前邁進。 一旦到達任一列表的末尾,就完成了。
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)) {
...
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.