Java - запутался в компараторах и должен использовать один (я думаю). Подробнее внутри

Я создал класс под названием Foo. Foo имеет три поля, все целочисленные: x, y и z. Я хочу сделать PriorityQueue<Foo>, который по-разному расставляет приоритеты для объектов Foo в разных ситуациях. Например, я мог бы захотеть расставить приоритеты по значению x, или, может быть, по значению y, или, может быть, по z. Но я не буду знать, какое значение я хочу расставить по приоритетам, до времени выполнения. Я слышал, что вы можете использовать компараторы, чтобы каким-то образом навязать порядок на лету, что, я думаю, было бы идеально здесь.

Я смущен тем, как именно я бы это сделал. Может ли кто-нибудь показать мне пример, если я хочу расставить приоритеты по x с помощью компаратора (без переопределения функции compareTo в моем классе Foo)?

Большое спасибо.


person Tim    schedule 13.02.2012    source источник
comment
Это отличный способ начать: stackoverflow.com/questions/683041/   -  person Nicolas Modrzyk    schedule 13.02.2012
comment
Вам не нужно ничего переопределять, но ваш класс Foo должен будет реализовать < i>Интерфейс компаратора. Просто добавьте метод compare(a,b), и он вернет целое число меньше нуля, если a ‹ b, ноль, если a == b, и целое число больше нуля, если a > b.   -  person Stevens Miller    schedule 13.02.2012


Ответы (1)


Компаратор — это параметризованный интерфейс, который позволяет определить, как можно сравнивать два экземпляра параметризованного типа. предположим, у вас есть следующий класс

class Foo {
   int x;
   int y;
   int z;
}

Затем, чтобы определить компаратор, который упорядочивает элементы на основе их значения x, затем y, а затем z, мы должны сделать следующее

class XyzComparator implements Comparator<Foo> {
    @Override
    public int compare(Foo foo1, Foo foo2) {
          if(foo1.x != foo2.x) {
               return Integer.compare(foo1.x, foo2.x);
          }
          if(foo1.y != foo2.y) {
               return Integer.compare(foo1.y, foo2.y);
          }
          return Integer.compare(foo1.z, foo2.z);
    }
}

Точно так же вы можете определить компраторы, которые сравнивают элементы сначала на основе их значения y, затем x z... и т. д. Наконец, во время выполнения вы можете создать экземпляр PriorityQueue с этим компаратором.

PriorityQueue<Foo> queue;
if(x_then_y_then_z) {
    queue = new PriorityQueue<Foo>(10, new XyzComparator());
} else if (y_then_x_then_z) {
    queue = new PriorityQueue<Foo>(10, new ZxyComparator());
}

Для получения дополнительной информации см. документ приоритетной очереди, а также сопоставитель javadoc

Редактировать: см. комментарий @buritos относительно целочисленного переполнения.

person 271828183    schedule 13.02.2012
comment
что нарушает контракт компаратора. использование вычитания в сравнении при работе с числами кажется правильным, но что, если foo1.y = -2147483648 и foo2.y = 1? очевидно, что foo1.y меньше, чем foo2.y, но foo1.y-foo2.y = 2147483647 (из-за молчаливого переполнения int), что явно не то, что вам нужно в результате вашей функции сравнения. - person buritos; 13.02.2012
comment
Очень проницательно. Спасибо. Я обновлю код, чтобы отразить это. - person 271828183; 13.02.2012