Какой неизменный объект работает с List.contains? - PullRequest
0 голосов
/ 27 марта 2020

Я хочу создать список координат и иметь возможность проверить, содержит ли этот список новую координату.

Я пытался реализовать Pair, но использование List.contains() с Pair не работает, всегда возвращая false.

Какие еще объекты я могу использовать, чтобы иметь возможность проверить List.contains()?

Ответы [ 3 ]

4 голосов
/ 27 марта 2020

Вероятно, это связано с тем, что ваша реализация Pair не предоставляет переопределенный метод equals. Я смог воспроизвести вашу проблему, используя следующий код:

//a plain POJO, in Pair.java
public class Pair<A, B> {
    private A a;
    private B b;

    public Pair(A a, B b) {
        this.a = a;
        this.b = b;
    }

    public A getA() {
        return a;
    }

    public B getB() {
        return b;
    }
}

//... Main.java

public class Main {
    public static void main(String[] args) {
        List<Pair<Integer, String>> list = new ArrayList<>();
        Pair<Integer, String> one = new Pair<>(1, "hello");
        Pair<Integer, String> two = new Pair<>(1, "hello");
        list.add(one);
        System.out.println(list.contains(two));
    }
}

Это распечатывает false, потому что List.contains использует равенство объектов в качестве теста (метод по умолчанию equals в классе Object ). Например, в приведенном выше коде one.equals(two) оценивается как false, потому что это не один и тот же объект. Чтобы исправить это, вы должны предоставить метод equals, который просматривает каждое поле и сравнивает их по отдельности:

//in class Pair
@Override
public boolean equals(Object o) {
    if (this == o) return true;
    if (o == null || getClass() != o.getClass()) return false;
    Pair<?, ?> pair = (Pair<?, ?>) o;
    return Objects.equals(a, pair.a) &&
            Objects.equals(b, pair.b);
}

Вы можете делегировать довольно утомительную и подверженную ошибкам задачу написания этого кода в вашей IDE , Я использую Intellij, и это только вопрос нажатия Code/Generate/equals() and hashcode(). Вам не нужен hashcode() для этого конкретного случая, но всегда полезно хранить вместе equals() и hashcode(). Теперь, когда List.contains попытается найти элемент, который соответствует предоставленному вами, он будет использовать этот новый и более подходящий метод. Если вы снова запустите метод main, вы увидите, что он оценивается как true.

0 голосов
/ 27 марта 2020

List.contains проверяет, равны ли два объекта, используя метод Object.equals. Следовательно, он работает только с объектами, для которых реализован метод Object.equals. Если вы пишете свой собственный класс Pair, убедитесь, что вы указали ему метод equals.

0 голосов
/ 27 марта 2020

Я думаю, что ваша пара содержит то же значение, но объект не тот же. Это потому что это не работает. Вместо этого вы можете использовать карту.

Как использовать карту:

Map<String, Integer> map = new HashMap<>();
map.put("Hello", 0); // add key an value to map (Key: "Hello", Value: 0)
map.put("World", 1); // add key an value to map (Key: "World", Value: 1)

if (map.containsKey("World")) { // check if map contains key: "World"
  System.out.println(map.get("World")); // try return value by key: returns 1
  System.out.println(map.get("world")); // try return value by key: returns null
}

if (map.containsKey("Hello")) { // check if map contains key: "Hello"
  System.out.println(map.get("Hello")); // try return value by key: returns 0
  System.out.println(map.get("hello")); // try return value by key: returns null
}
...