2009-07-12 2 views
2

Мне любопытно. Что может быть причиной того, что компаратор перемещает записи в каждом запуске приложения ?Странное поведение: Java Comparator рандомизирует записи списка

final static class ContactsListComparator implements Comparator 
{       
    public int compare(Object o1, Object o2) 
    { 
     if((o1.toString().compareTo(o2.toString()))<0) 
     { 
      return -1; 
     } 
     if((o1.toString().compareTo(o2.toString()))>0) 
     { 
      return 1; 
     } 
     else 
     { 
      return 0; 
     } 
    }  
}  

Первый App Начало:

alt text

Второй App Start

alt text

Как уже упоминалось в одном ответ

Компаратор фактически сравнивает пользовательский объект Контакт

public class Contact 
{ 
    // Members 
    private String _contactFirstName; 
    private String _contactLastName; 
    private long _contactLastModified; 

// Constructor 
public Contact() 
{ 
    set_contactLastModified(); 
} 

public Contact(String contactFirstName) 
{ 
    _contactFirstName = contactFirstName; 
    set_contactLastModified(); 
} 

// Accessable Getters 
public String get_contactFirstName() 
{ 
    return _contactFirstName; 
} 

public String get_contactLastName() 
{ 
    return _contactLastName; 
} 

public long get_contactLastModified() 
{ 
    return _contactLastModified; 
} 

public void set_contactLastModified() 
{ 
    _contactLastModified = System.currentTimeMillis(); 
} 
    } 
+0

больше кода необходимо. Как вы использовали этот компаратор? – Pierre

+0

Я бы внимательно посмотрел, что делает метод toString(). Он может, например, просто перечислить серийный идентификатор объекта. –

ответ

14

Ваш метод toString, вероятно, не переопределяется для объектов, представляющих контакты. Он вернет хэш-строку для этих объектов, которая меняется при каждом запуске вашего приложения.

Вы можете исправить это одним из двух способов:

  • Override метод toString() в вашем Contact объекте, чтобы вернуть имя контакта (1), или
  • Изменения Comparator к Comparator<Contact> поэтому он получает Contact объектов в качестве параметров (2)

для (1), добавьте в ваш класс Контакты:

@Override public String toString() { 
    return get_contactFirstName(); 
} 

для (2), вы бы в конечном итоге с этой реализации Comparator:

final static class ContactsListComparator implements Comparator<Contact> {       
    public int compare(Contact o1, Contact o2) { 
     return contact1.get_contactFirstName().compareTo(contact2.get_contactFirstName()); 
    } 
} 

вам даже не нужно, чтобы проверить на < 0 или> 0, но вы можете просто вернуться независимо сравнение Струнный дает.

+0

правильный! =) ((ContactsListObject) o1) .get_contactFirstName(). CompareTo (((ContactsListObject) o2) .get_contactFirstName()) –

+0

Sweet catch, bravo! – javamonkey79

2

Я хотел бы использовать:

final static class ContactsListComparator implements Comparator<Contact> 
{ 
public int compare(Contact c1,Contact c2) 
{ 
int i=c1.get_contactLastName().compareTo(c2.get_contactLastName()); 
if(i!=0) return i; 
return c1.get_contactFirstName().compareTo(c2.get_contactFirstName());; 
} 

} 
+0

Компаратору нужен минимум JRE 1.5, не так ли? –

+0

да, дженерики были введены в 1.5 – Jorn

+0

, они не будут работать в J2ME, хотя - надо придерживаться уродливого кастинга! –

2

Ваш первый пример в основном такой же, как

final static class ContactsListComparator implements Comparator {       
    public int compare(Object o1, Object o2) { 
     return o1.toString().compareTo(o2.toString()); 
    }  
} 

Это будет работать, если вы переопределить ToString(), как

public String toString() { 
    return _contactFirstName + ' ' + _contactLastName; 
} 

Однако, компаратор, который сравнивает предполагаемые поля, лучше, как было предложено.