Легко измените метод .contains () в интерфейсе Коллекции в Java для утверждения равенства - PullRequest
1 голос
/ 25 апреля 2020

Мне интересно, есть ли способ легко изменить метод ".contains ()" в интерфейсе List в Java без создания пользовательского класса. Например:

При работе с коллекцией массивов в java метод .contains () всегда будет возвращать false, потому что метод .contains () всегда проверяет равенство с обобщенными c .equals () вызов из класса Object, который возвращает true, только если сравниваемые объекты имеют одинаковые ссылки в памяти. Однако с массивами гораздо полезнее выполнить проверку Arrays.equals () для двух массивов.

Код:

public class Temp {
    public static void main(String[] args) {
        int[] myIntArray = new int[] {1, 2, 3};
        List<int[]> myList = new ArrayList<>();
        myList.add(myIntArray);
        System.out.println(myList.contains(new int[] {1, 2, 3}));
    } // Output in the console: false
    // Preferred output: true
}

Я понимаю, что это можно сделать довольно просто, используя for для l oop и итерируя по всему списку с помощью метода Arrays.equals (), но цель для меня - научиться легко ваять метод .contains () в то, что мне нужно для будущего использования , Большое спасибо!

Ответы [ 2 ]

3 голосов
/ 25 апреля 2020

Нет. contains() не может делать ничего, кроме использования Object.equals, потому что это требуется спецификацией.

Нельзя сказать, что не разумно хотеть понятие содержимого для массива; просто вы не можете перегрузить существующую концепцию.

Вы можете просто создать метод stati c:

static <T> boolean containsArray(List<? extends T[]> list, T[] query) {
  return list.stream().anyMatch(e -> Arrays.equals(e, query));
}

И затем вызывать его там, где в противном случае вы вызываете list.contains(query).

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

(Вышеприведенное будет работать для любого массива ссылочного типа. Вам нужно будет специализировать его для массивов примитивного типа).

Он также имеет то преимущество, что вам не нужно иметь дело с острые последствия, выделенные Стивеном C (например, как работают indexOf, remove et c).


Есть еще одна альтернатива: используйте тип элемента списка, который поддерживает равных "правильно". Например, вы можете обернуть массивы, используя Arrays.asList, чтобы сохранить их в списке, так что у вас есть List<List<T>> вместо List<T[]>.

Это было бы довольно агрессивным изменением: это потребовало бы изменения тип списка в вашем коде; вы не указали, насколько широко используется ваш список массивов.

2 голосов
/ 25 апреля 2020

Мне интересно, есть ли способ легко изменить метод contains в интерфейсе List в Java без создания пользовательского класса.

Нет пути. Метод contains стандартных реализаций List ведет себя так, как указано в List API; то есть они используют метод equals.

С другой стороны, нетрудно расширить класс ArrayList и переопределить contains, чтобы сделать то, что вы хотите. Но если вы делаете это правильно, вам нужно подумать, хотите ли вы:

  • indexOf и lastIndexOf, чтобы они соответствовали contains
  • семантике equals(Object) чтобы соответствовать этому
  • семантика списка, возвращаемого sublist(int, int), чтобы соответствовать семантике основного списка.
...