Есть ли эффективный и более быстрый способ переопределить метод compareTo (), используемый в TreeSet - PullRequest
0 голосов
/ 14 мая 2019

Я читаю таблицу, содержащую шесть столбцов, и перехожу в коллекцию TreeSet. Это работает должным образом, однако, мне просто любопытно, если есть более эффективный способ перегрузки compareTo() метод. Причина, по которой я спрашиваю об этом, состоит в том, что у меня будут дополнительные наборы с большим количеством столбцов, и то, как я это делаю, кажется мне неэффективным и трудоемким. Важно отметить, что все элементы класса my являются целыми числами.

Кроме того, у меня есть дополнительный вопрос. Содержит ли одно из заданий метода compareTo() предотвращение дублирования, как HashCode() в HashMap()?

Ниже я покажу, как определить метод compareTo().

    public int compareTo(Network o) {
        int r = this.headNode > o.headNode? 1 : this.headNode < o.headNode ? -1   :  0;
        if(r==0) { r = this.headPeriod1 > o.headPeriod1? 1 :  this.headPeriod1 < o.headPeriod1? -1 : 0;
            if(r==0) {
                r = this.headPeriod2 > o.headPeriod2? 1 :  this.headPeriod2 < o.headPeriod2? -1 : 0;
                if(r==0) {
                    r = this.tailNode > o.tailNode? 1 :  this.tailNode < o. tailNode? -1 : 0;
                        if(r==0) {
                            r = this.tailPeriod1 > o.tailPeriod1 ? 1 :  this.tailPeriod1 < o.tailPeriod1 ? -1 : 0;
                                if(r==0) {
                                    r = this.tailPeriod2 > o.tailPeriod2 ? 1 :  this.tailPeriod2 < o.tailPeriod2 ? -1 : 0;
                                }
                        }
                }
            }
        }

Ответы [ 3 ]

3 голосов
/ 14 мая 2019

Вы можете создать компаратор, чтобы сделать его более читабельным:

public class Test {

    int age;
    int money;
    int id;

    public Test(int age, int money, int id) {
        this.age = age;
        this.money = money;
        this.id = id;
    }

    public static void main(String... args) {

        Test t1 = new Test(25,200,3);
        Test t2 = new Test(30,50,5);
        Test t3 = new Test(15,90,9);

        Comparator<Test> comp = Comparator.<Test>comparingInt(x -> x.age)
                                            .thenComparingInt(x -> x.money)
                                            .thenComparingInt(x -> x.id);

        Set<Test> set = new TreeSet<>(comp); // Pass the comparator to the Treeset, TreeMap, etc., or use it inside of you Comparable.compareTo method.

        set.add(t1);
        set.add(t2);
        set.add(t3);

        System.out.println(set); // [Test{age=15, money=90, id=9}, Test{age=25, money=200, id=3}, Test{age=30, money=50, id=5}]
    }

    @Override
    public String toString() {
        return "Test{" + "age=" + age + ", money=" + money + ", id=" + id + '}';
    }
}

Как видите, вы можете использовать Comparator.comparingInt (x -> x. headNode ) .thenComparingInt (x -> x. headPeriod2 ) .thenComparingInt (x -> x. tailNode ) ...

и т. Д., Чтобы сделать его более значимым. Вы можете продолжать добавлять больше этих .thenComparingInt ... по мере роста вашего класса. Это отсортирует их по headNode, затем по headPeriod2, затем по tailNode и т. Д.

(вместо x используйте любое имя для этой переменной, например (network -> network.headNode)

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

Если вы реализуете Comparable и хотите использовать ваш Comparator внутри вашего метода CompareTo , тогда поместите созданный Comparator в качестве поля экземпляра и используйте компаратор внутри compteT, например:

public class Test implements Comparable<Test>{

    int age;
    int money;
    int id;

    Comparator<Test> comp = Comparator.<Test>comparingInt(x -> x.age)
                                            .thenComparingInt(x -> x.money)
                                            .thenComparingInt(x -> x.id);

    public Test(int age, int money, int id) {
        this.age = age;
        this.money = money;
        this.id = id;
    }

    public static void main(String... args) {

        Test t1 = new Test(25,200,3);
        Test t2 = new Test(30,50,5);
        Test t3 = new Test(15,90,9);

        Set<Test> set = new TreeSet<>();

        set.add(t1);
        set.add(t2);
        set.add(t3);

        System.out.println(set); // [Test{age=15, money=90, id=9}, Test{age=25, money=200, id=3}, Test{age=30, money=50, id=5}]
    }

    @Override
    public String toString() {
        return "Test{" + "age=" + age + ", money=" + money + ", id=" + id + '}';
    }

    @Override
    public int compareTo(Test o) {
        return comp.compare(this, o);
    }

}

со ссылкой на метод:

public class Test implements Comparable<Test>{

    private int age;
    private int money;
    private int id;

    private final Comparator<Test> comp = Comparator.<Test>comparingInt(Test::getId)
                                            .thenComparingInt(Test::getMoney)
                                            .thenComparingInt(Test::getAge);

    public static void main(String... args) {

        Test t1 = new Test(25, 200, 3);
        Test t2 = new Test(30, 50, 5);
        Test t3 = new Test(15, 90, 9);

        Set<Test> set = new TreeSet<>();

        set.add(t1);
        set.add(t2);
        set.add(t3);

        System.out.println(set); // [Test{age=25, money=200, id=3}, Test{age=30, money=50, id=5}, Test{age=15, money=90, id=9}]
    }

    public Test(int age, int money, int id) {
        this.age = age;
        this.money = money;
        this.id = id;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public int getMoney() {
        return money;
    }

    public void setMoney(int money) {
        this.money = money;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    @Override
    public int compareTo(Test o) {
        return comp.compare(this, o);
    }

    @Override
    public String toString() {
        return "Test{" + "age=" + age + ", money=" + money + ", id=" + id + '}';
    } 
}

Надеюсь, это поможет.

1 голос
/ 15 мая 2019

Как бы вы это ни делали, я бы настоятельно не стал вычитать значения, чтобы получить <или> результаты компаратора. Это может привести к ошибкам и является плохой привычкой. Проверьте следующее:


      int val1 = -1223222022;
      int val2 = 2130200022;
      int result = compareTo(val1, val2);
      // This shows val1 > val2
      if (result < 0) {
         System.out.println(val1 + " < " + val2);
      }
      else if (result > 0) {
         System.out.println(val1 + " > " + val2);
      }

      val1 = 1234450392;
      val2 = -2022030049;
      result = compareTo(val1, val2);
      //this shows val2 < val2
      if (result < 0) {
         System.out.println(val1 + " < " + val2);
      }
      else if (result > 0) {
         System.out.println(val1 + " > " + val2);
      }
   }

   public static int compareTo(int a, int b) {
      return a - b;
   }

Просто используйте функциональный интерфейс Comparable, чтобы привести в порядок ваши требования.

1 голос
/ 14 мая 2019

Это было бы немного короче / проще:

   public int compareTo(Network o) {
        int r = this.headNode - o.headNode;
        if (r == 0) {
            r = this.headPeriod1 - o.headPeriod1;
            if (r == 0) {
                r = this.headPeriod2 - o.headPeriod2;
                if (r == 0) {
                    r = this.tailNode - o.tailNode;
                    if (r == 0) {
                        r = this.tailPeriod1 - o.tailPeriod1;
                        if (r == 0) {
                            r = this.tailPeriod2 - o.tailPeriod2;
                        }
                    }
                }
            }
        }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...