Сортировка по нескольким полям - PullRequest
1 голос
/ 20 августа 2011

Я пытаюсь сначала отсортировать по марке машины , затем отсортировать по году выпуска машины , а затем отсортировать по пробегу машины . Все поля являются строками.

Вот что я пробовал до сих пор:

class Sorter implements Comparator<Car> {
  @Override
  public int compare(Car o1, Car o2) {
    if(o1.getMake().compareToIgnoreCase(o2.getMake()) == 0 && Integer.parseInt(o1.getYear()) != Integer.parseInt(o2.getYear())){
      if(Integer.parseInt(o1.getYear()) > Integer.parseInt(o2.getYear())){
        return -1;
      }else{
        return 1;
      }
    }
    if(o1.getMake().compareToIgnoreCase(o2.getMake()) == 0 && Integer.parseInt(o1.getYear()) == Integer.parseInt(o2.getYear())){
      if(Integer.parseInt(o1.getMileage()) > Integer.parseInt(o2.getMileage())){
        return 1;
      }else{
        return -1;
      }
    }
    return o1.getMake().compareToIgnoreCase(o2.getMake());

  }
}

Я пытаюсь построить алгоритм, который вы могли бы использовать в Excel, где вы можете упорядочить по одному столбцу, затем другому, затем другому.

Ответы [ 5 ]

1 голос
/ 20 августа 2011

Если класс имеет несколько значимых полей, порядок, в котором вы сравнивать их критично. Вы должны начать с самого значительного поле и проложите себе путь вниз. Если сравнение приводит к чему-либо кроме нуля (который представляет равенство), вы сделали; просто вернись результат. Если наиболее значимые поля равны, продолжайте сравнивать следующие наиболее значимые поля и так далее. Если все поля равны, объекты равны; вернуть ноль .. (Эффективная Java).

public int compare(Car car1, Car car2) {
    // compare make 
    int makeDiff = car1.getMake().compare(car2.getMake());
    if ( makeDiff != 0 )
        return makeDiff;

    // compare year
    int yearDiff = car1.getYear().compare(car2.getYear());
    if ( yearDiff != 0 )
        return yearDiff;

    // compare mileage
    int mileageDiff = car1.getMileage().compare(car2.getMileage());
    if ( mileageDiff != 0 )
        return mileageDiff;

    return 0;
}
1 голос
/ 20 августа 2011

Общий подход называется лексикографический порядок , который мы используем для сортировки слов.Предполагая, что мы хотим отсортировать два объекта класса C по полям f1, f2 ... fn, мы поступим следующим образом:

  1. Сравните два поля f1;если они различаются, результатом сравнения является конечный результат, в противном случае
  2. Повторите для каждого из следующих полей.

В коде (будьте осторожны - не скомпилировано):

class Sorter implements Comparator<Car> {
  @Override
  public int compare(Car o1, Car o2) {
    int res = o1.getMake().compareToIgnoreCase(o2.getMake());
    if ( res != 0 )
      return res;
    res = o1.getYear().compareTo(o2.getYear());
    if ( res != 0 )
      return res;
    return Integer.parseInt(o1.getMileage()).compareTo(Integer.parseInt(o2.getMileage()));
  }
}
0 голосов
/ 28 сентября 2011

Посмотрите на ComparatorChain из коллекции Apache Commons.
На следующем сайте у меня есть учебное пособие: Сортировка объектов по нескольким атрибутам

0 голосов
/ 20 августа 2011

Я пытаюсь отсортировать сначала по марке автомобиля, затем по году автомобиля, а затем по пробегу.Все поля являются строками.

A) Вы должны изменить свой дизайн.Год должен быть int, пробег должен быть int, float или объектом, состоящим из одного из них и Unit.Строки просто не правильное представление.Кроме того, если вы используете их в Comparator, вам придется преобразовывать их в правильный тип, по крайней мере, один раз за сравнение, что ужасно неэффективно,

b) Для реализации Comparators вы, вероятно, захотите использоватьвнешняя библиотека.И Guava, и Commons / Lang довольно хороши в этом.В следующем примере я предполагаю, что Год и Пробег являются числовыми.

Гуава (ComparisonChain):

public int compare(Car o1, Car o2) {
    return ComparisonChain.start()
       .compare(o1.getYear(), o2.getYear())
       .compare(o1.getMileage(), o2.getMileage())
       .compare(o1.getMake(), o2.getMake())
       .getResult();
}

Commons / Lang (CompareToBuilder):

public int compare(Car o1, Car o2) {
    return new CompareToBuilder()
       .append(o1.getYear(), o2.getYear())
       .append(o1.getMileage(), o2.getMileage())
       .append(o1.getMake(), o2.getMake())
       .toComparison();
}

Как видите, обе версии оченьпохожи, а также гораздо проще, чем сами кодировать.

0 голосов
/ 20 августа 2011

Я бы написал MultiComparator вроде следующего:

class MultiComparator<T> implements Comparator<T> {
  private final List<Comparator<T>> comparators = new ArrayList<Comparator<T>>();
  public MultiComparator(final List<Comparator<T>> comps) { ... }
  @Override int compareTo(T t1, T t2) {
    for (Comparator<T> c: comparators) {
      int d = c.compareTo(t1, t2);
      if (d != 0) return d;
    }
    return 0;
  }
}

Затем вы создаете экземпляр MultiComparator<T> с 3 независимыми компараторами, каждый из которых сравнивает только одно из указанных вами полей. Тогда вы получите желаемый результат.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...