После того, как я использую метод .toArray()
в приоритетной очереди целых чисел, я получаю такой массив объектов:
Object[] objects = pq.toArray();
Однако мне нужно, чтобы массив был int[]
. Я пробовал:
int [] arr = (int[]) objects;
но он говорит:
Cannot cast from Object[] to int[]
Как я могу этого добиться?
Все коллекции предоставляют альтернативную реализацию toArray
с указанием типа элемента:
Integer[] objects = pq.toArray(Integer[]::new);
Обратите внимание, что для этого требуется Java v11 или выше.
Обратите внимание, что в этом случае результирующий массив, очевидно, представляет собой целочисленные объекты-оболочки, не знаю, подходит ли это для ваших требований.
РЕДАКТИРОВАТЬ - быстрый тест:
PriorityQueue<Integer> q = new PriorityQueue<>();
q.add(42);
System.out.println(Arrays.toString(q.toArray(Integer[]::new)));
Целевой тип этого выражения должен быть функциональным интерфейсом.
Несовместимый список параметров для конструктора массива. Ожидалось (int), но найдено ()
Это 3 сообщения об ошибках, которые я получаю, когда использую это выражение.
@PabloBiedma Пожалуйста, опубликуйте объявление своей очереди. Ваш пост подразумевает, что это было PriorityQueue<Integer>
?
PriorityQueue<Integer> pq = new PriorityQueue<>();
Добавил тестовый код к моему ответу, выглядит точно так же, как ваш, странно. Вы используете Java v8+, да?
@stridecolossus Ваше текущее решение не может работать: есть две toArray
s. Первый из интерфейса Collection
требует предоставления целевого массива, скажем q.toArray(new Integer[q.size()])
. Второй, из интерфейса BaseStream
, требует фабричного метода для создания массива заданной длины, скажем, q.stream().toArray(Integer[]::new)
. Вы смешали оба в один, поэтому он не работает.
@fluffy Ничего общего с потоками, это метод по умолчанию в базовом классе коллекции: docs.oracle.com/javase/7/docs/api/java/util/…. Также обратите внимание, что есть две реализации.
@stridecolossus Это часть того, о чем я говорю. Пожалуйста, перечитайте. Ваш код не может скомпилироваться из-за смешения идей из обоих toArray
s. Вы запутались с этим: docs.oracle.com/javase/8/docs/api/java/util/stream/…
@fluffy Попробуйте код, он компилируется и запускается, это именно то, что я сделал! Пример из JavaDoc делает именно это: String[] y = x.toArray(String[]::new)
. Также обратите внимание на делегаты реализации по умолчанию для другой реализации toArray
.
@stridecolossus Вы понимаете, что x.toArray(new String[0]);
(из примера) — это не то же самое, что x.toArray(String[]::new)
? Опять же, javac
отклоняет ваше решение, помеченное как «быстрый тест» с помощью error: no suitable method found for toArray(Integer[]::new)
.
@fluffy @Pablo Biedma Какую версию Java вы используете? Реализация toArray
, которую я использовал в приведенном выше фрагменте, — это @since 11
. Если вы используете более старую версию, то, очевидно, этот метод не существует, поэтому возникает ошибка.
@stridecolossus Извините, не понял, что вы имеете в виду docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/… начиная с Java 11 (Я все еще в мире Java 8, и новые методы, подобные этим, в очень старых интерфейсах проходят мимо меня). Теперь это имеет смысл.
@fluffy Да, я только что понял, что разместил старую версию JavaDoc, чтобы еще больше запутать ситуацию, да! Измененный ответ соответственно.
@stridecolossus Еще раз извините за это. Я знаю о выпусках Java после 8, но обычно не обращаю особого внимания на изменения API, особенно те, которые затрагивают старые API, но уделяю больше внимания языковым изменениям. Так вот где моя "древность" из мира Java 8 сыграла роль неверного истолкования. Я был действительно сбит с толку старым справочником Javadoc 7, поэтому я подумал, что это опечатка, которая смешивает вещи. Хорошего дня и спасибо за пометку «Java 11+» к вашему ответу!
@fluffy Не беспокойтесь, я был так же сбит с толку, как и вы, я ожидаю! Приносим извинения за публикацию «древней» ссылки на JavaDoc, которая только еще больше запутала ситуацию. Мы добрались туда в конце концов.
Это не то, что вы можете легко сделать.
Возможно, вы знаете, что Object[] на самом деле просто заполнен целыми числами, а это значит, что его можно привести, верно?
Проблема в том, что переменная «объекты» все еще существует. И в Object[] вам разрешено помещать любой Object. Итак, после вашего приведения кто-то может сделать что-то вроде:
objects[0] = "some string";
Так что же тогда должно произойти? Должен ли ваш int[] внезапно стать недействительным, поскольку теперь он содержит строку? Следует ли запрещать вводить данные, отличные от целых чисел, в objects
, что обычно позволяет это делать?
Кастинг просто означает, что вы указываете на одно и то же, но смотрите на это по-разному. Что вам нужно сделать, так это преобразовать его. На это уже есть ответ:
java-преобразование массива строк в массив целых чисел
Так что простой кастинг здесь не поможет.
Обновление: ответ @stridecolossus, вероятно, так же хорош, как и тот, на который я ссылался.
Поскольку PriorityQueue реализует Collection , вы можете использовать поток для перебора его элементов и сопоставления их с int
:
PriorityQueue<Integer> pq = new PriorityQueue<>(Arrays.asList(1, 2, 5));
int[] arr = pq.stream().mapToInt(Integer::intValue).toArray();
System.out.println(Arrays.toString(arr)); // [1, 2, 5]
Метод toArray(T[]) в типе PriorityQueue<Integer> неприменим для аргументов (Integer[]::new)