Java - Объркан съм с компараторите и трябва да използвам такъв (мисля). Повече информация вътре

Създадох клас, наречен Foo. Foo има три полета, които са int: 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) и го накарайте да върне int по-малко от нула, ако a ‹ b, нула, ако a == b, и int, по-голямо от нула, ако 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 за приоритетна опашка, както и компаратора 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