Подтвердить что ты не робот

Java: для использования содержит в ArrayList полный пользовательский объект, если я переопределяю equals или реализую Comparable/Comparator?

У меня есть полный массив ArrayList:

class TransitionState {

    Position positionA;
    Position positionB;

    int counter;

    public boolean equals (Object o){

        if (o instanceof TransitionState){

          TransitionState transitionState= (TransitionState)o;

          if ((this.positionA.equals(transitionState.positionA))
                  &&(this.positionB.equals(transitionState.positionB)))
          {
              return true;
          }
        }
     return false;

    }

    @Override
    public String toString() {

        String output = "Position A " + positionA.i+ " "+ positionA.j + " "+ positionA.orientation + " "+
                "Position B " + positionB.i + " "+ positionB.j + " "+ positionB.orientation;

        return output;
    }

}

class Position {

    int i;
    int j;
    char orientation;

    Position() {

    }


    void setIJ(int i, int j){
        this.i=i;
        this.j=j;
    }

    void setOrientation(char c){

        orientation = c;
    }

   public boolean equals(Object o){

        if(o instanceof Position){

          Position p = (Position)o;
          if((p.i==this.i)&&(p.j==this.j)&&(p.orientation==this.orientation))
          {
              return true;
          }
              else return false;

        }

            return false;
   }

} //end class Position

Я запрошу его с помощью этого:

 if(!transitionStatesArray.contains(newTransitionState)){  //if the transition state is new add and enqueue new robot positions

                 transitionStatesArray.add(newTransitionState); //marks as visited

Я нахожу повторяющиеся элементы внутри своего transitionStatesArray, почему это?

Я использую эти значения i, j и ориентации для заполнения уникальных значений в матрице, но здесь у меня есть дубликат:

 S  .  N 
 *  *  * 
 .  D  D 


 E  .  O 
 *  *  * 
 .  D  D 


 N  .  S 
 *  *  * 
 .  D  D 


 S  .  N 
 *  *  * 
 .  D  D 
4b9b3361

Ответ 1

Метод List.contains(...) определяется как использовать equals(Object), чтобы решить, содержит ли объект аргумента список. Поэтому вам нужно переопределить equals... при условии, что реализация по умолчанию - это не то, что вам нужно.

Однако вам нужно знать, что List.contains(...) потенциально проверяет аргумент против каждого элемента в списке. Для длинного списка это дорого. В зависимости от деталей вашего приложения может быть лучше использовать другой тип коллекции (например, HashSet, TreeSet или LinkedHashSet) вместо List. Если вы используете один из них, ваш класс должен будет переопределить hashCode или реализовать Comparable, или вам нужно будет создать отдельный Comparator... в зависимости от того, что вы выберете.


(Немного больше советов по альтернативам... поскольку OP заинтересован)

Производительность contains для типа List типа ArrayList или LinkedList равна O(N). Наихудшая стоимость вызова contains прямо пропорциональна длине списка.

При a TreeSet наихудшая производительность contains пропорциональна log2(N).

Для HashSet или LinkedHashSet средняя производительность contains является константой, независимой от размера коллекции, но наихудшая производительность - O(N). (Наихудшая производительность возникает, если вы 1) реализуете плохую функцию hashcode(), которая хэширует все до небольшого числа значений или 2) настраивает параметр "коэффициент загрузки", чтобы хеш-таблица не изменялась автоматически по мере ее роста.)

Недостатком использования классов Set является:

  • они являются множествами; т.е. вы не можете поместить в коллекцию два или более "равных" объектов, а
  • они не могут быть проиндексированы; например нет метода get(pos) и
  • некоторые из классов Set даже не сохраняют порядок вставки.

Эти проблемы необходимо учитывать при определении того, какой класс коллекции использовать.

Ответ 2

Вероятно, вам нужно реализовать hashCode(). В общем, вы всегда должны делать это, когда переопределение равно.

Из коллекций docs:

Эта спецификация не должна быть подразумевается, что вызов Collection.contains с ненулевым аргумент o приведет к тому, что o.equals(e) для любого элемента e. Реализации могут быть бесплатными для реализации оптимизация, при которой равны вызова можно избежать, например, путем сначала сравнение хэш-кодов два элемента. (Object.hashCode() спецификация гарантирует, что два объекты с неравными хэш-кодами не могут быть равным.) В более общем плане, реализации различных Интерфейсы коллекции Framework бесплатно воспользоваться заданное поведение Объектные методы везде, где разработчик считает это целесообразным.