Метод Содержит () ArrayList всегда возвращает ложь с пользовательским объектом - PullRequest
0 голосов
/ 13 сентября 2018

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

class Sign {

  private String char;
  private Integer freq;

  public Sign(String c) {
  this.char = c; 
  }

  @Override
  public boolean equals(Object o) {

   String check = (String)o;
   return check.equals(this.char);
  }

  @Override
  public int hashCode() {

    int hash = 7;
    hash = 31 * hash + this.char.hashCode();
    return hash;
}

}

Я предполагаю, что всегда будет метод String в равных по причинам простоты.Также есть некоторый hashCode (), чтобы убедиться, что метод contains () будет работать, и вот сам тест:

    ArrayList<Sign> queueOfSigns = new ArrayList<>();

    Sign test = new Sign("C");
    String c = "C";
    queueOfSigns.add(test);

    if(queueOfSigns.contains("C"))
        System.out.println("I am here!");

Независимо от того, что этот простой тестовый код всегда возвращает false в этом случае - так "Я здесь "сообщение никогда не появляется.Я пробовал несколько разных подходов к моему коду, но это было потому, что идея этого состоит в том, чтобы получить отдельные символы из текста String и проверить, присутствует ли один символ в ArrayList.Тем не менее - без того, чтобы этот простой тест не работал должным образом, я не могу двигаться дальше, поэтому я хотел бы спросить вас - что мне не хватает.На самом деле я впервые использую методы equals () и hashCode (), чтобы мой собственный объект работал должным образом с методом contains ().

Ответы [ 2 ]

0 голосов
/ 13 сентября 2018

Ваш equals метод реализован неправильно.Это нарушает общий контракт Object.equals:

  • Это не является рефлексивным - поскольку выдает исключение, когда аргумент не является строкой, x.equals(x), где xSign будет аварийно завершать работу с исключением.
  • Это не симметрично - x.equals(y) не возвращает то же значение, что и y.equals(x), если y является строкой, а x является Sign
  • Это не согласовано - поскольку оно может генерировать исключения, когда аргумент не является строкой, а не просто возвращать истину или ложь.

На низком уровне абстракции,Причиной этой проблемы является реализация contains.Согласно документам:

Возвращает true, если этот список содержит указанный элемент.Более формально, возвращает true, если и только если этот список содержит хотя бы один элемент e такой, что (o == null? E == null: o.equals (e)).

ArrayListфактически вызывает o.equals(e) с o строкой, которую вы передали. Таким образом, он на самом деле вызывает метод equals в String.

Если contains вызывается e.equals(o), то ваша программа будет иметьнапечатано «Я здесь», но ваш equals все еще нарушает контракт.

Лучшая реализация equals выглядит примерно так:

@Override
public boolean equals(Object o) {
    if (o == null) {
        return false;
    }

    if (o.getClass() == this.getClass()) {
        Sign other = (Sign)o;
        return other.$char.equals($char); // I have renamed 'char' to '$char' since the former is not a valid identifier
    } else {
        return false;
    }
}

И ваш код клиента:

    ArrayList<Sign> queueOfSigns = new ArrayList<>();

    Sign test = new Sign("C");
    Sign c = new Sign("C");
    queueOfSigns.add(test);

    if(queueOfSigns.contains(c))
        System.out.println("I am here!");

РЕДАКТИРОВАТЬ:

Я думаю, это то, что вы ищете:

arrayList.stream()
    .filter(x -> x.getChar().equals("C"))
    .findFirst().isPresent() // this returns true if a sign with C is found in the array list
0 голосов
/ 13 сентября 2018

Ваша equals реализация неверна.equals имеет конкретный контракт;этот код пытается нарушить этот контракт.Из документации:

Метод equals реализует отношение эквивалентности для ненулевых ссылок на объекты:

  • возврат : для любого неnull опорное значение x, x.equals(x) должен возвращать true
  • это симметричны * * +1020:. для любых не- null эталонных значений * +1022 * и * * +1023, x.equals(y) должен возвращать true тогда и только тогда, когда y.equals(x) возвращает true.
  • Это переходный : для любых не null опорных значений x,y и z, если x.equals(y) возвращает true и y.equals(z) возвращает true, то x.equals(z) должно вернуть true.
  • Это согласовано : для любых не null опорных значений x и y множественные вызовы x.equals(y) последовательно возвращают true или последовательно возвращают false, при условии, что никакая информация, используемая в equals сравнениях объектов, не являетсямодифицировано.

Там нет никакого способа, чтобы сделатьn экземпляр вашего Sign класса equals в строку.

...