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

Arrays.asList(int []) не работает

Когда я запускаю следующий код, вывод не выводится.

int[] array = {3, 2, 5, 4};

if (Arrays.asList(array).contains(3))
{
    System.out.println("The array contains 3");
}
4b9b3361

Ответ 1

Когда вы передаете массив примитивов (int[] в вашем случае) в Arrays.asList, он создает List<int[]> с одним элементом - самим массивом. Поэтому contains(3) возвращает false. contains(array) вернет true.

Если вы используете Integer[] вместо int[], он будет работать.

Integer[] array = {3, 2, 5, 4};

if (Arrays.asList(array).contains(3))
{
  System.out.println("The array contains 3");
}

Дальнейшее объяснение:

Подпись asList равна List<T> asList(T...). Примитив не может заменить параметр типового типа. Поэтому, когда вы переходите к этому методу int[], весь массив int[] заменяет T и вы получаете List<int[]>. С другой стороны, когда вы передаете Integer[] этому методу, Integer заменяет T и вы получаете List<Integer>.

Ответ 2

В Java 8 вам не нужно вообще преобразовывать массив; просто превратите его в поток через Arrays#stream, затем используйте предикат anyMatch, чтобы узнать, содержится ли значение в массиве.

int[] array = {3, 2, 5, 4};

if (Arrays.stream(array).anyMatch(x -> x == 3)) {
    System.out.println("The array contains 3");
}

Ответ 3

Предыдущий ответ объясняет, почему ваш подход не работает.

Чтобы достичь того, что вам нравится, вы также можете использовать утилиты Apache Commons Lang:

import org.apache.commons.lang.ArrayUtils;
...
int[] array = {3, 2, 5, 4};
ArrayUtils.contains(array, 3);

Ответ 4

Arrays.asList(T... a) принимает T[] для любого типа объекта T который будет соответствовать любому массиву объектов (то есть вещам, которые являются подклассом Object). Единственное, что не соответствует, - это массив примитивов, поскольку примитивные типы не являются производными от Object. То есть int[] не является (подклассом) Object[].

Затем происходит то, что механизм varags включается и обрабатывает его, как если бы вы передали один объект, и создает массив одного элемента этого типа. Таким образом, вы передаете int[][] (здесь T - int[]) и в итоге получаете 1-элементный List<int[]> что не то, что вам нужно.

У вас все еще есть несколько неплохих вариантов:

Guava Int.asList(int[]) Адаптер

Если ваш проект уже использует guava, это так же просто, как использование адаптера, предоставляемого Guava: Int.asList(). Существует аналогичный адаптер для каждого примитивного типа в связанном классе, например, Booleans для boolean и т.д.

Ваша функция может быть записана как:

int[] array = {3, 2, 5, 4};
if (Ints.asList(array).contains(3))
{
    System.out.println("The array contains 3");
}

Преимущество этого подхода заключается в том, что он создает тонкую оболочку вокруг существующего массива, поэтому создание оболочки занимает постоянное время (не зависит от размера массива), а требуемая память - только небольшая постоянная величина ( менее 100 байт) в дополнение к базовому целочисленному массиву.

Недостатком является то, что для доступа к каждому элементу требуется операция упаковки базового объекта int, а настройка требует распаковки. Это может привести к большому количеству временного выделения памяти, если вы активно обращаетесь к списку. В вашем игрушечном примере во время поиска будет только одна операция упаковки, так как элемент будет найден немедленно. Точно так же алгоритмы, такие как бинарный поиск, которые редко обращаются к массиву, вероятно, будут работать разумно.

Однако если вы в среднем обращаетесь к каждому объекту много раз, может быть лучше использовать реализацию, которая упаковывает объекты один раз и сохраняет их как Integer. Это может быть так же просто, как сделать копию списка: new ArrayList<>(Ints.asList(array)), или вы в Java 8 можете использовать IntStream.boxed() (описанный ниже) для создания List<Integer>. Оба должны работать примерно одинаково.

Java 8 IntStream

Как описано в ответе Arrays.stream(int[]), вы можете использовать метод Arrays.stream(int[]) чтобы превратить массив int в Stream. В зависимости от вашего IntStream.anyMatch() использования вы можете использовать поток напрямую, например, чтобы определить, существует ли элемент 3, вы можете использовать IntStream.anyMatch(). В этом случае это решение является очень быстрым и не влечет за собой никакой упаковки или распаковки и не создает никакой копии базового массива.

С другой стороны, если вам действительно нужен List<Integer>, вы можете использовать stream.boxed().collect(Collectors.toList()) как предлагается здесь. Недостатком этого подхода является то, что он полностью упаковывает каждый элемент в списке, что может увеличить его объем памяти почти на порядок, он создает новый Object[] для хранения всех элементов в штучной упаковке. Если впоследствии вы интенсивно используете список и вам нужны объекты типа Integer а не int s, это может окупиться, но об этом нужно знать.