#java #arrays #arraylist #contains
#java #массивы #arraylist #содержит
Вопрос:
У меня есть ArrayList, который содержит массивы. Как мне проверить, содержит ли ArrayList указанный массив? Я использовал .contains
метод, и он возвращает false
вместо ожидаемого true
.
import java.util.ArrayList;
import java.util.Arrays;
public class main {
public static void main(String[] args) {
ArrayList<String[]> action = new ArrayList<String[]>();
action.add(new String[]{"appple", "ball"});
String[] items = new String[]{"appple", "ball"};
if (action.contains(new String[]{"appple", "ball"})) {
System.out.println("Yes");
}
System.out.println(action.contains(items)); // False
}
}
Комментарии:
1. Это выглядит как плохой дизайн с самого начала. Рассмотрите возможность создания
List<List<String>>
или переноса массива в класс, который используетjava.util.Arrays.equals
иjava.util.Arrays.hashCode
как свои собственные методы equals и hashCode .
Ответ №1:
Метод ‘contains’ сравнивает эквивалентные значения хэш-кода.
Поэтому, если вы сделаете это, как показано ниже *, оно пройдет.
public class main {
public static void main(String[] args) {
ArrayList<String[]> action = new ArrayList<String[]>();
String[] items = new String[]{"appple","ball"};
action.add(items);
System.out.println("TO STRING");
System.out.println("--" action.get(0));
System.out.println("--" new String[]{"apple","ball"});
System.out.println("HASHCODES");
String[] sameValues = new String[]{"apple","ball"};
System.out.println("--" action.get(0).hashCode());
System.out.println("--" items.hashCode());
System.out.println("--" sameValues.hashCode());
System.out.println("CONTAINS");
System.out.println("--" action.contains(items)); // *this
System.out.println("--" action.contains(sameValues));
System.out.println("--" action.contains(new String[]{"apple","ball"}));
}
}
результат:
TO STRING
--[Ljava.lang.String;@7b1d7fff
--[Ljava.lang.String;@299a06ac
HASHCODES
--1243554231
--1243554231
--2548778887
CONTAINS
--true
--false
--false
Что касается кода, показанного при печати массива, они не переопределяются toString()
, поэтому вы получаете:
getClass().getName() '@' Integer.toHexString(hashCode())
Например:
[Ljava.lang.String;@7b1d7fff
[
обозначает одномерный массивLjava.lang.String
обозначает тип@
7b1d7fff
Шестнадцатеричное представление хэш-кода
Однако, если вы хотите сравнить значения, существует следующий метод.
public class main {
public static void main(String[] args) {
String[] items = new String[]{"apple","ball"};
ArrayList<String> action = new ArrayList<>(Arrays.asList(items));
if (action.contains("apple")) {
System.out.println("Yes");
}
}
}
Ответ №2:
Вы можете выполнить итерацию по этому списку и для каждого элемента, т.Е. Массива, Вызвать Arrays.equals
метод для проверки равенства массивов до первого совпадения или до конца списка, если ни один из них не совпадает. В этом случае он может возвращать true
для каждого элемента:
List<String[]> list = List.of(
new String[]{"appple", "ball"},
new String[]{"appple", "ball"});
String[] act = new String[]{"appple", "ball"};
System.out.println(list.stream()
.anyMatch(arr -> Arrays.equals(arr, act))); // true
Этот метод внутренне вызывает String#equals
метод для каждого элемента массива, т. Е. String
, Поэтому этот код также возвращает true
:
List<String[]> list = List.of(
new String[]{new String("appple"), new String("ball")},
new String[]{new String("appple"), new String("ball")});
String[] act = new String[]{new String("appple"), new String("ball")};
System.out.println(list.stream()
.anyMatch(arr -> Arrays.equals(arr, act))); // true
Ответ №3:
Поскольку вы создаете разные массивы (даже если содержимое одинаковое), contains приведет к false .
Однако, если вы сделаете это:
List<String[]> action = new ArrayList<String[]>();
String[] items = new String[]{"apple","ball"};
action.add(items);
if (action.contains(items))
System.out.println("Yes");
Это выведет Yes.
Кроме того, некоторые примеры поведения:
String[] items = new String[]{"apple","ball"};
action.add(items);
String[] clone = items.clone();
String[] mirror = items;
action.contains(clone); // false
action.contains(mirror); // true
items[0]="horse";
System.out.println(mirror[0]); // "horse"
System.out.println(clone[0]); // "apple"
System.out.println(action.get(0)[0]); // "horse"
mirror[1]="crazy";
System.out.println(clone[1]); // "ball"
System.out.println(action.get(0)[1]); // "crazy"
System.out.println(items[1]); // "crazy"
clone[1]="yolo";
System.out.println(action.get(0)[1]); // "crazy"
System.out.println(items[1]); // "crazy"
System.out.println(mirror[1]); // "crazy"
System.out.println(action.get(0).hashCode()); //2018699554
System.out.println(items.hashCode()); //2018699554
System.out.println(clone.hashCode()); //1311053135
System.out.println(mirror.hashCode()); //2018699554
Пользовательский « contains
«
Проблема здесь в том, что если вы захотите впоследствии выполнить поиск по определенному массиву, вы потеряете ссылки, и поиск элемента будет невозможен, даже не реплицируя массив с теми же точными значениями.
В качестве обходного пути вы можете реализовать свой собственный contains
метод. Что-то вроде:
Если вы хотите получить индекс:
static int indexOfArray(List<String[]> list, String[] twin)
{
for (int i=0;i<list.size();i )
if (Arrays.equals(list.get(i),twin))
return i;
return -1;
}
А затем вызовите его следующим образом:
String[] toSearch = new String[]{"apple","ball"};
int index = indexOfArray(action, toSearch);
if (index>0)
System.out.println("Array found at index " index);
else
System.out.println("Array not found");
Если индекс больше -1, вы можете получить свой исходный массив, просто:
String[] myArray = action.get(index);
Хэш — карта идентификатор
Альтернативой может быть сохранение массивов в a HashMap
путем объявления идентификатора для каждого массива. Например:
Идентификатор Base64
Это даст тот же результат для тех же значений, поскольку закодированное значение основано на записях, а не на ссылке на объект.
static String getIdentifier(String[] array)
{
String all="";
for (String s : array)
all =s;
return Base64.getEncoder().encodeToString(all.getBytes());
}
И тогда вы могли бы:
Map<String, String[]> arrayMap= new HashMap<>();
String[] items = new String[]{"apple","pear", "banana"}; // *[1234]
action.add(items);
arrayMap.put(getIdentifier(items), items); // id = QUJDYWFh
//....
//Directly finding the twin will fail
String[] toSearch = new String[]{"apple","pear", "banana"}; // *[1556]
System.out.println(action.contains(toSearch)); // false
//But if we get the identifier based on the values
String arrId = getIdentifier(toSearch); // id = QUJDYWFh
System.out.println(action.contains(arrayMap.get(arrId))); //true
//arrayMap.get(arrId)-> *[1234]
//.....
Имя.
Выберите представительное имя и используйте его в качестве идентификатора
Map<String, String[]> arrayMap= new HashMap<>();
String[] items = new String[]{"apple","pear", "banana"};
action.add(items);
arrayMap.put("fruits", items);
//...
System.out.println(action.contains(arrayMap.get("fruits"))); // true
Комментарии:
1.
The issue here is that if you want to search for an specific array afterwards, you'd lose the references and searching an item wouldn't be possible, not even replicating the array with the same exact values.
Супер странно. Где я могу прочитать больше об этом?2. Это именно то, что происходит в вашем вопросе. Вы знаете, какие значения, вы реплицируете массив по точкам, и все равно сообщает вам, что он его не содержит. Это потому, что хэш-код вашего первого массива равен 1234, а второго — 1554 (упрощенный). Даже при одинаковых значениях это разные объекты.
3.
String[] copy = items.clone()
при вызовеitems.equals(copy)
результат будет false . Почему? Протестируйте его.System.out.println(copy.hashCode());
иSystem.out.println(items.hashCode());
не тот же хэш-код, даже для клона.4. @JJ123 dzone.com/articles/object-identity-and-equality-in-java
Ответ №4:
Согласно JavaDocs, метод «contains» использует методы «equals» и «hashCode», чтобы проверить, содержится ли объект.
Наводящий вопрос: знаете ли вы, какова реализация «equals» для массивов?
Проверьте это, и вы, вероятно, поймете результат выполнения вашего кода (подсказка: ==).
Как сказал «Корабль на воздушной подушке, полный угрей», лучшим дизайном будет использование списка некоторой коллекции, которую вы понимаете / контролируете, это методы «equals» и «hashCode».