2016-08-26 2 views
3

Я хочу, чтобы иметь возможность возвращать позицию объекта с помощью метода indexOf, но только хочу передать имя контакта для поиска этого, есть ли способ для это нужно сделать?Использование IndexOf с customObject в 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

Heres функция, которая будет достичь этого, не проходя через весь список, я думаю, что сложность меньше, чем 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). Вы можете выполнять половину итераций в своем for-loop, но вы все еще проверяете каждый элемент. Это не лучше, чем повторение всего этого по одному. – 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)» в связанном списке (vs «O (1)» в списке «RandomAccess», ArrayList'). –

1

Если вы делаете много поисков Contacts по имени, вы можете поместить экземпляры в Map<String, Contacts>. Конкретный тип Map зависит от ваших требований; a HashMap может быть достаточно.

Вместо contactList.add(contacts), вы можете использовать:

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

, а затем посмотреть пункт на карте, используя:

contactMap.get(someName); 

Это будет быстрее делать Lookups чем сканирование по списку каждый раз: каждый поиск будет 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 надлежащим образом.

Ваши равные могут определять равенство, основанное на имени, поэтому удаляя все лишний и ненужный код.

Смежные вопросы