Как использовать compareTo() для одной указанной переменной-члена

Пожалуйста, может кто-нибудь предложить наилучшее решение следующей проблемы (это часть программы, которую я пытаюсь закодировать):

У меня есть класс Foo с переменными-членами и другой класс Bar, который расширяет Foo. Bar добавляет дополнительные переменные-члены. Объекты Bar хранятся в коллекции, и поэтому я хотел бы упорядочить эти объекты по любой из их переменных-членов.

Я рассматривал возможность использования типа enum, содержащего переменные-члены для классов, которые можно было бы передать в качестве аргумента методу compareTo(), но, поскольку перечисляемые типы являются неявно статическими, я не могу добавлять параметры для переменных-членов для Bar или любых других классов, которые могут расширяться Фу, что я хочу сравнить. Например, я хочу сравнить два класса Bar по переменной-члену myVar, которую я бы назвал как-то вроде bar1.compareTo(bar2, MyEnum.MYVAR), и классы будут сравниваться с их значениями myVar. Я думаю, что мне, возможно, просто придется создать отдельные методы для упорядочения каждой переменной-члена, но я хочу использовать compareTo(), поскольку он используется коллекциями Java для автоматической сортировки своих элементов (я считаю).

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

РЕДАКТИРОВАТЬ. Это похоже на сортировку столбцов в окне проводника Windows по различным атрибутам, например, дате изменения, имени файла, размеру и т. д.


person user1886491    schedule 07.12.2012    source источник
comment
Мммм....compareTo принимает только один аргумент. Почему бы просто не переопределить compareTo в Bar?   -  person    schedule 08.12.2012
comment
Я уже переопределяю compareTo в Bar, моя проблема заключается в сортировке коллекции Bar по указанной переменной-члену.   -  person user1886491    schedule 08.12.2012
comment
Я предполагаю, что некоторые фрагменты кода могут улучшить читаемость и ясность вопроса. Во всяком случае, это хорошее начало, это ваш первый вопрос.   -  person Giulio Muscarello    schedule 08.12.2012
comment
compareTo не сортирует. compareTo сравнивает. Используйте sort для сортировки.   -  person    schedule 08.12.2012


Ответы (2)


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

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

person Fritz    schedule 07.12.2012
comment
Вы также можете создать компаратор, который принимает в своем конструкторе аргумент, указывающий, какое поле использовать для сравнения. Таким образом, вам нужен только один компаратор, и его можно использовать для сортировки по разным полям. - person jahroy; 08.12.2012
comment
@jahroy Пока он реализует интерфейс Comparator, никакого вреда не будет. Единственное, вам нужно проверить, какое поле вы будете использовать, что немного усложняет код. Также бывает случай, когда сравнение не такое тривиальное, или когда есть сравнение по нескольким полям. В любом случае, это хороший момент. - person Fritz; 08.12.2012
comment
Было бы неплохо, если бы каждое возможное поле сортировки реализовывало сопоставимые. Очевидно, есть случаи, когда это было бы нетривиально реализовать. Вот ответ с примером: stackoverflow.com/a/4136060/778118 - person jahroy; 08.12.2012
comment
Я знаю, что Вы имеете ввиду. Я не против идеи компаратора для простых полей, но IMO, имеющая дополнительные компараторы для других сложных сравнений, сделала бы код намного чище. - person Fritz; 08.12.2012
comment
Ага. Вообще не спорю с этим. Несколько компараторов - хорошее решение. При этом вот еще одна ссылка, показывающая пример динамического компаратора: stackoverflow.com/a/13577772/778118 - person jahroy; 08.12.2012
comment
@jahroy, последняя ссылка, которую вы разместили, - это именно то, что я искал, сейчас пойду и реализую ее. Есть ли кнопка благодарности в stackoverflow? новичок - person user1886491; 08.12.2012
comment
Здесь нет кнопки благодарности, но вы можете голосовать за ответы и комментарии, которые считаете полезными. Вы должны проголосовать за этот ответ и ответ по моей ссылке (если вы решите и сможете). - person jahroy; 08.12.2012

Очень сложно реализовать compareTo с использованием наследования. Лучше не делай этого. Используйте агрегацию, и у вас не будет проблем:

class Bar {
  Foo foo;
  String barName;
  public getName() { return barName; }
}

Кроме того, если вам нужны разные методы компаратора (например, по возрастанию, по убыванию, по атрибуту), определите Comparator : (unfort. У меня Eclipse не открыт, исправьте, если синтаксис не работает)

public class BarComparator implements Comparator<Bar> {

      @Override
      public int compare(Bar b1, Bar b2) {
        if (b1.getName() == null && b2.getName() == null) {
          return 0;
        }
        if (b1.getName() == null) {
          return 1;
        }
        if (b2.getName() == null) {
          return -1;
        }
        return b1.getName().compareTo(b2.getName());
      }
    }
person AlexWien    schedule 07.12.2012
comment
В вашем примере делается попытка назначить новый Comparable Comparator. Это не сработает (очевидно). Компаратор имеет два метода: compare и equals. - person jahroy; 08.12.2012