Как я могу использовать пользовательский класс в наборе деревьев?

#java #java-7

#java #набор деревьев

Вопрос:

Если бы я использовал Set аналогичный этому:

 Set<node> s=new TreeSet<node>();

class node {

  private int x;
  private int y;

}
  

Будет ли это приемлемо, и, поскольку это TreeSet, будет ли он также сортировать его?

Ответ №1:

Он не сможет отсортировать его без вашей реализации Comparable<Node> , и он не будет действительно подходящим для операций set, пока вы не переопределите equals() и hashCode() . (Вам не нужно переопределять equals и hashCode для TreeSet работы, но это имело бы смысл сделать.)

Что-то вроде этого:

 final class Node implements Comparable<Node> {

  private final int x;
  private final int y;

  Node(int x, int y) {
    this.x = x;
    this.y = y;
  }

  @Override public boolean equals(Object other) {
    if (!(other instanceof Node)) {
      return false;
    }
    Node otherNode = (Node) other;
    return x == otherNode.x amp;amp; y == otherNode.y;
  }

  @Override public int hashCode() {
    return x * 31   y * 17; // For example...
  }

  @Override public int compareTo(Node other) {
    // As of Java 7, this can be replaced with
    // return x != other.x ? Integer.compare(x, other.x) 
    //     : Integer.compare(y, other.y);

    if (x < other.x || (x == other.x amp;amp; y < other.y)) {
      return -1;
    }
    return x == other.x amp;amp; y == other.y ? 0 : 1;
  }
}
  

(Обратите внимание, что по соглашению имя класса будет Node , а не node .)

Комментарии:

1. в чем причина его создания final class ?

2. @medopal: равенство и другие вещи становится сложнее реализовать правильно (когда даже есть представление о правильности), когда задействовано наследование. Аналогично, когда я знаю, что подклассов нет, я знаю, что он неизменяем. В основном я подписываюсь на «дизайн для наследования или запрещаю его».

3. или «в зависимости от варианта использования» используйте guava или apache commons, чтобы избежать ветвления в вашем коде и позволить библиотеке реализовать метод hashcode и equals .

4. @Carlos: Нет, отсюда и предложение «Вам не нужно переопределять equals и hashCode для работы TreeSet, но это имело бы смысл сделать». Мне гораздо легче рассуждать о коде, когда сопоставимые реализации также подчиняются естественному равенству.

5. «Обратите внимание, что null не является экземпляром какого-либо класса, и e.compareTo(null) должен вызывать исключение NullPointerException, даже если e.equals(null) возвращает false». Удалите первый оператор if.

Ответ №2:

Узел должен реализовать сопоставимый, или вам нужно передать пользовательский компаратор, который может сравнивать два объекта узла. Кроме того, любая коллекция на основе хэша зависит от объекта, соответствующим образом переопределяющего equals() и hashcode() метод.

Комментарии:

1. К вашему сведению, TreeSet не основан на хэше.

2. @Bohemian да, вы правы, TreeSet или TreeMap специально не используют хеширование.

Ответ №3:

Вы должны указать equals, hashCode и реализовать сопоставимый интерфейс

Комментарии:

1. На самом деле это неверно. Достаточно просто сопоставимого. Вы должны реализовать equals() , но Object.equals() и Object.hashcode() по умолчанию достаточны для «работы» — в этом нет «необходимости».

Ответ №4:

В коде нет ничего плохого в том, что касается принятия as. Но для сортировки Node класс ДОЛЖЕН реализовывать сопоставимый интерфейс.