2015-01-21 5 views
1

У меня есть класс с несколькими свойствами. Я хочу, чтобы он отсортировался. В настоящее время я сортировка по Name так:Сортировка коллекции по двум различным свойствам

Collections.sort(rowItems, new Comparator() { 

    public int compare(Object o1, Object o2) { 
     SearchRowItem p1 = (SearchRowItem) o1; 
     SearchRowItem p2 = (SearchRowItem) o2; 
     return p1.getName().compareToIgnoreCase(p2.getName()); 
    } 

}); 

Но я также хочу, чтобы сортировать LastName вторично к Name (так что если имена совпадают сортировать по LastName вторым). Как мне совместить мой код ниже с моим первым видом, чтобы получить результат, который я описал?

Collections.sort(rowItems, new Comparator() { 

    public int compare(Object o1, Object o2) { 
     SearchRowItem p1 = (SearchRowItem) o1; 
     SearchRowItem p2 = (SearchRowItem) o2; 
     return p1.getLastName().compareToIgnoreCase(p2.getLastName()); 
    } 

}); 

ответ

3

Простой Comparator что первый сравнивающий name и затем lastName будет работать с методом Collections.sort.

От JavaDoc:

Сравнивает свои два аргумента для заказа. Возвращает отрицательное целое число, ноль или положительное целое число, поскольку первый аргумент меньше, равен или больше второго.


Итак, вот пример Comparator, который сравнивает с двумя свойствами:

Collections.sort(rowItems, new Comparator<SearchRowItem>() { 
    @Override 
    public int compare(final SearchRowItem o1, final SearchRowItem o2) { 
     int compare = o1.getName().compareToIgnoreCase(o2.getName()); 
     if (compare != 0) { 
      return compare; 
     } 
     return o1.getLastName().compareToIgnoreCase(o2.getLastName()); 
    } 
}); 

Однако, есть и другие альтернативы. Java 8 представила потоки, где сортировка хорошо интегрируется. Вместе с новыми методами Comparator.comparing и thenCompare можно создать красивый поток.

final List<SearchRowItem> collect = rowItems.stream() 
     .sorted(
       Comparator.comparing(SearchRowItem::getName, String::compareToIgnoreCase) 
          .thenComparing(SearchRowItem::getLastName, String::compareToIgnoreCase)) 
     .collect(Collectors.toList()); 

Обратите внимание, что последний не сортирует оригинальный List, но создает новый отсортированный список.

+0

Благодарим вас за такой подробный ответ, это помогло мне реально понять сортировку. – BluGeni

+0

Рад, что я мог бы помочь! – wassgren

1

Проверка на равенство в первом сравнении

public int compare(Object o1, Object o2) { 
      SearchRowItem p1 = (SearchRowItem) o1; 
      SearchRowItem p2 = (SearchRowItem) o2; 
      int compare = p1.getName().compareToIgnoreCase(p2.getName()); 
      if (compare == 0) { 
       compare = p1.getLastName().compareToIgnoreCase(p2.getLastName()); 
      } 
      return compare; 
     } 
2

Если getName() возвращает 0 это означает, что оба объекта имеют одинаковые имена - только тогда вы должны использовать getLastName():

Collections.sort(rowItems, new Comparator() { 

    @Override 
    public int compare(Object o1, Object o2) { 
     SearchRowItem p1 = (SearchRowItem) o1; 
     SearchRowItem p2 = (SearchRowItem) o2; 
     int nameComp = p1.getName().compareToIgnoreCase(p2.getName()); 
     if (nameComp != 0) { 
      return nameComp; 
     } 
     return p1.getLastName().compareToIgnoreCase(p2.getLastName()); 
    } 
}); 

EDIT :
Ответ выше следует стилю OP. Тем не менее, если это возможно, следует использовать дженерики, чтобы очистить код:

Collections.sort(rowItems, new Comparator<SearchRowItem>() { 

    @Override 
    public int compare(SearchRowItem p1, SearchRowItem p2) { 
     int nameComp = p1.getName().compareToIgnoreCase(p2.getName()); 
     if (nameComp != 0) { 
      return nameComp; 
     } 
     return p1.getLastName().compareToIgnoreCase(p2.getLastName()); 
    } 
}); 
Смежные вопросы