2016-08-26 76 views
3

我想要能夠使用indexOf方法返回對象的位置,但只想傳遞聯繫人的名稱來搜索此,有什麼辦法可以這要完成了嗎?使用indexOf與arrayList中的自定義對象

我現在有這樣的方法:

private static ArrayList<Contacts> contactList = new ArrayList<Contacts>(); 

public class Contacts { 
private String name; 
private String number; 


public Contacts(String name, String number) { 
    this.name = name; 
    this.number = number; 
} 

public String getName() { 
    return name; 
} 

public String getNumber() { 
    return number; 
} 

public void setName(String name) { 
    this.name = name; 
} 

public void setNumber(String number) { 
    this.number = number; 
} 



public int findItem(String name) { 

    return contactList.indexOf(name); 
} 

回答

1

繼承人,將做到這一點,而無需通過整個列表會的功能,我覺得複雜度小於O(N):

public int findItem(String name) 
    { 
     int max = contactList.size(); 

     //you might have to subtract this by one 
     //I'm not sure off the top 
     int descCnt = max; 


     for(int cnt = 0; cnt <= max/2; cnt++) 
     { 
      if(contactList.get(cnt).getName().equals(name)) return cnt; 
      if(contactList.get(descCnt).getName().equals(name)) return descCnt; 
      --descCnt; 
     } 

    } 
+0

不,它仍然是O(n)。這種「優化」可能會讓事情變得更慢,因爲從列表的任何一端獲取項目都可能導致更多的緩存抓取。 –

+0

複雜度爲O(n)。你可能會在循環中做一半的迭代,但你仍然在檢查每一個元素。這並不比逐個迭代整個事物更好。 – nasukkin

+0

我明白了。謝謝你的澄清。我覺得這樣平均會讓你更快地得到答案? @AndyTurner –

0

你所要求的不在List#indexOf(Object)的合同中,所以不,你不應該試圖讓清單以這種方式工作。

取而代之,您可以編寫自己的方法來完成相對容易的任務。只需遍歷列表並找到與指定名稱匹配的聯繫人即可。

/** 
* Returns the List index of the Contact with the specified name. If no such 
* Contact is found, -1 will be returned. 
*/ 
public int findItem(String name) { 
    for (int i = 0; i < contactList.size(); i++) { 
     Contact contact = contactList.get(i); 
     if (null == contact) continue; 
     if (java.lang.Objects.equals(name, contact.getName())) return i; 
    } 
    return -1; 
} 
+0

@SamOrozco那麼?這個問題沒有提到性能問題。即使如此,這種方法也可以像任意ArrayList一樣好。現在,如果數組按名稱排序,我們可以做一些更好的搜索並將複雜度降低到O(ln(n)),但同樣,這個問題沒有提到複雜性要求和排序能力。 – nasukkin

+0

對不起我之前的評論我很困惑。 –

0

我想補充的傢伙,我已經能夠做到這一點是這樣的:

public void searchItem(String name) { 
    for(int i = 0; i < contactList.size(); i++) { 
     if(name.equals(contactList.get(i).getName())) { 
      System.out.println("Found " + name); 
      break; 
     } 
     else { 
      System.out.println("Could not find name!"); 
     } 
    } 
} 

然而,這是不是相當低效的,如果我有一個更大的名單?有沒有更有效的方法來做到這一點?

+0

效率低下?您是否在應用程序中遇到這種性能問題,您需要擔心優化您所寫的內容?請記住:過早優化是所有邪惡的根源。你在這裏寫的是通過你的列表搜索的好方法。 – nasukkin

+0

'contactList'是一個'ArrayList',所以這將會非常有效(除非在每次迭代中打印'Could not find name',直到找到該項目爲止)。如果將其更改爲LinkedList(例如),效率會更低,因爲鏈表中的列表檢索爲「O(n)」(與「RandomAccess」列表中的「O(1)」相似, ArrayList')。 –

1

如果您按名稱進行了大量Contacts查找,則可以將實例放入Map<String, Contacts>Map的具體類型取決於您的要求;一個HashMap可能就足夠了。

相反的contactList.add(contacts),你可以使用:

contactMap.put(contacts.getName(), contacts); 

,然後使用查找項目在地圖:

contactMap.get(someName); 

這將以更快的速度做查找不是通過清單掃描每次:每個查詢將爲O(1)HashMap,而O(n)爲一個列表。但是,它使用更多的內存。


順便說一句,你Contacts類看起來像它代表一個單一的接觸,所以它應該被命名爲單數:Contact

此外,您find方法目前聲明爲實例方法:

public int findItem(String name) { 

這意味着你實際上需要的Contacts實例找到Contacts另一個實例。相反,聲明它static

public static int findItem(String name) { 

那麼你可以調用它沒有一個實例:

Contacts found = Contacts.find("name"); 
0

如果你有興趣。更好的方法是覆蓋對象中的equals()和hashcode()。並以正確的方式使用indexOf。

您的等於可以根據名稱確定相等性,因此可以刪除所有額外的和不必要的代碼。