2016-08-26 2 views
3

Ich möchte in der Lage sein, die Position eines Objekts mit der Methode indexOf zurückzugeben, aber nur den Namen des Kontakts übergeben, um nach diesem zu suchen, gibt es eine Möglichkeit für das zu tun?Verwenden von IndexOf mit einem customObject in einer ArrayList

Im Moment habe ich diese Methode:

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); 
} 

Antwort

1

Heres eine Funktion, die dies ohne den Umweg über die ganze Liste erreichen, denke ich, die Komplexität weniger als 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

Nein, es ist immer noch O (n). Diese Art von "Optimierung" macht die Dinge wahrscheinlich langsamer, weil das Abrufen von Elementen von beiden Enden der Liste mehr Cache-Fetches verursachen kann. –

+0

Die Komplexität ist O (n). Sie machen vielleicht halb so viele Iterationen in Ihrer for-Schleife, aber Sie überprüfen immer noch jedes Element. Das ist nicht besser, als das Ganze eins nach dem anderen zu wiederholen. – nasukkin

+0

Ich sehe. Danke für die Abklärung. Ich fühle, dass dies im Durchschnitt dich schneller auf die Antwort bringen wird? @AndyTurner –

0

Was Sie fragen, ist nicht im Vertrag von List#indexOf(Object), also nein, Sie sollten nicht versuchen, die Liste auf diese Weise arbeiten zu lassen.

Stattdessen können Sie Ihre eigene Methode schreiben, die relativ leicht erreichen wird, was Sie wollen. Iterieren Sie einfach über Ihre Liste und suchen Sie den Kontakt, der dem angegebenen Namen entspricht.

/** 
* 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 So? Die Frage erwähnt keine Leistungsbedenken. Trotzdem ist diese Methode für eine beliebige ArrayList so gut wie möglich. Wenn nun das Array nach dem Namen sortiert ist, können wir etwas raffinierter suchen und die Komplexität auf O (In (n)) reduzieren, aber die Frage erwähnt weder die Komplexitätsanforderungen noch die Sortierbarkeit. – nasukkin

+0

Sorry über meinen früheren Kommentar Ich war verwirrt. –

0

Gerade Jungs an, ich habe in der Lage gewesen, es auf diese Weise zu tun:

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!"); 
     } 
    } 
} 

Dies ist jedoch nicht recht ineffizient, wenn ich eine größere Liste haben war? Gibt es einen effizienteren Weg, dies zu tun?

+0

Ineffizient? Treten in Ihrer Anwendung solche Leistungsprobleme auf, dass Sie sich Gedanken darüber machen müssen, was Sie geschrieben haben? Denken Sie daran: vorzeitige Optimierung ist die Wurzel allen Übels. Was Sie hier geschrieben haben, ist eine gute Möglichkeit, Ihre Liste zu durchsuchen. – nasukkin

+0

'contactList' ist eine' ArrayList', also wäre dies einigermaßen effizient (außer dass 'Name nicht gefunden' bei jeder Iteration gefunden wird, bis Sie das Objekt gefunden haben). Wenn Sie es zum Beispiel in eine 'LinkedList' geändert haben, wäre es weniger effizient, da der Listenabruf in einer verknüpften Liste 'O (n)' ist (gegen 'O (1)' in einer 'RandomAccess'-Liste wie' ArrayListe'). –

1

Wenn Sie viele Nachschlagevorgänge von Contacts mit Namen durchführen, können Sie die Instanzen in eine Map<String, Contacts> setzen. Der spezifische Typ von Map hängt von Ihren Anforderungen ab; ein HashMap könnte ausreichen.

Statt contactList.add(contacts), können Sie verwenden:

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

und dann auf ein Element in der Karte nachschauen mit:

contactMap.get(someName); 

Dies wird schneller sein, die Lookups zu tun, als eine Liste Scannen durch jedes Mal: ​​jeder Lookup wird O(1) für einen HashMap, im Vergleich zu O(n) für eine Liste sein. Es benötigt jedoch mehr Speicher.


übrigens Ihre Contacts Klasse sieht aus wie es einen einzigen Kontakt steht, so sollte es als singuläres genannt werden: Contact.

Auch Ihre find Methode wird zur Zeit als Instanz Methode deklariert:

public int findItem(String name) { 

bedeutet, dass Sie tatsächlich eine Instanz von Contacts brauchen eine andere Instanz von Contacts zu finden. Stattdessen erklären sie static:

public static int findItem(String name) { 

dann können Sie es ohne eine Instanz aufrufen kann:

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

Wenn Sie interessiert sind. Ein besserer Weg besteht darin, equals() und hashcode() in Ihrem Objekt zu überschreiben. Und benutze den Index auf die richtige Art und Weise.

Ihr Gleichgestellter könnte die Gleichheit basierend auf dem Namen bestimmen und daher all diesen zusätzlichen und unnötigen Code entfernen.

Verwandte Themen