Когда я запускаю следующий код, вывод не выводится.
int[] array = {3, 2, 5, 4};
if (Arrays.asList(array).contains(3))
{
System.out.println("The array contains 3");
}
Когда я запускаю следующий код, вывод не выводится.
int[] array = {3, 2, 5, 4};
if (Arrays.asList(array).contains(3))
{
System.out.println("The array contains 3");
}
Когда вы передаете массив примитивов (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>
.
В 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");
}
Предыдущий ответ объясняет, почему ваш подход не работает.
Чтобы достичь того, что вам нравится, вы также можете использовать утилиты Apache Commons Lang:
import org.apache.commons.lang.ArrayUtils;
...
int[] array = {3, 2, 5, 4};
ArrayUtils.contains(array, 3);
Arrays.asList(T... a)
принимает T[]
для любого типа объекта T
который будет соответствовать любому массиву объектов (то есть вещам, которые являются подклассом Object
). Единственное, что не соответствует, - это массив примитивов, поскольку примитивные типы не являются производными от Object
. То есть int[]
не является (подклассом) Object[]
.
Затем происходит то, что механизм varags включается и обрабатывает его, как если бы вы передали один объект, и создает массив одного элемента этого типа. Таким образом, вы передаете int[][]
(здесь T
- int[]
) и в итоге получаете 1-элементный List<int[]>
что не то, что вам нужно.
У вас все еще есть несколько неплохих вариантов:
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>
. Оба должны работать примерно одинаково.
Как описано в ответе Arrays.stream(int[])
, вы можете использовать метод Arrays.stream(int[])
чтобы превратить массив int
в Stream
. В зависимости от вашего IntStream.anyMatch()
использования вы можете использовать поток напрямую, например, чтобы определить, существует ли элемент 3
, вы можете использовать IntStream.anyMatch()
. В этом случае это решение является очень быстрым и не влечет за собой никакой упаковки или распаковки и не создает никакой копии базового массива.
С другой стороны, если вам действительно нужен List<Integer>
, вы можете использовать stream.boxed().collect(Collectors.toList())
как предлагается здесь. Недостатком этого подхода является то, что он полностью упаковывает каждый элемент в списке, что может увеличить его объем памяти почти на порядок, он создает новый Object[]
для хранения всех элементов в штучной упаковке. Если впоследствии вы интенсивно используете список и вам нужны объекты типа Integer
а не int
s, это может окупиться, но об этом нужно знать.