Обращение очереди <Integer> и преобразование ее в массив int
У меня есть Queue<Integer>
объявленная как Queue<Integer> queue=new LinkedList();
Мне нужно изменить порядок элементов в нем, а затем преобразовать его в массив int. Я написал ниже код:
Collections.reverse((List)queue);
int[] res=queue.stream().mapToInt(Integer::intValue).toArray();
Этот код имеет две проблемы:
- очередь на явное приведение
(List)queue
; - Интересно, есть ли однострочное решение?
Так есть ли у нас более элегантный способ сделать это?
Уточнение проблемы:
Является ли очередь перевернутой, не важно. Множество int обращенных элементов - это то, что мне нужно.
Ответы
Ответ 1
Во- первых, пожалуйста, не используйте сырые типы (используем оператор алмазную). Не совсем один вкладыш, но вы можете сначала преобразовать в int[]
а затем использовать commons lang ArrayUtils.reverse(int[])
как
Queue<Integer> queue = new LinkedList<>();
// ...
int[] arr = queue.stream().mapToInt(Integer::intValue).toArray();
ArrayUtils.reverse(arr);
Вы также можете написать свой собственный обратный метод int[]
который допускает свободный интерфейс (например, вернуть int[]
), тогда вы можете сделать его одним слоем. Подобно,
public static int[] reverse(int[] arr) {
for (int i = 0; i < arr.length / 2; i++) {
int temp = arr[i];
arr[i] = arr[arr.length - i - 1];
arr[arr.length - i - 1] = temp;
}
return arr;
}
А потом
int[] arr = reverse(queue.stream().mapToInt(Integer::intValue).toArray());
Ответ 2
Не нужно здесь фантазировать.
static int[] toReversedArray(Queue<Integer> queue) {
int i = queue.size();
int[] array = new int[i];
for (int element : queue) {
array[--i] = element;
}
return array;
}
Не однострочно, но легко читается и быстро.
Ответ 3
Collections.reverse
подразумевает только List
который является только одним типом Collection
, вы не можете преобразовать Queue
в List
. Но вы можете попробовать привести его к LinkedList
как:
Collections.reverse((LinkedList)queue);
Детали:
Я сомневаюсь, что есть встроенный API для реверсирования очереди. Вы все еще можете следовать обычному способу сделать это, используя Stack
:
Stack<Integer> stack = new Stack<>();
while (!queue.isEmpty()) {
stack.add(queue.remove());
}
while (!stack.isEmpty()) {
queue.add(stack.pop());
}
а затем преобразовать в массив, как вы будете
int[] res = queue.stream().mapToInt(Integer::intValue).toArray();
С другой стороны, если Deque
настоящее время удовлетворяет ваши потребности, вы можете просто положиться на сам LinkedList
, поскольку он также реализует Deque
. Тогда ваша текущая реализация будет такой простой:
LinkedList<Integer> dequeue = new LinkedList<>();
Collections.reverse(dequeue);
int[] res = dequeue.stream().mapToInt(Integer::intValue).toArray();
не является ли очередь измененной, не важно. Множество int обращенных элементов - это то, что мне нужно.
Другое решение из того, что уже предложили другие, - обратить Stream
в queue
и затем преобразовать mapToInt
в массив следующим образом:
Queue<Integer> queue = new LinkedList<>();
int[] res = reverse(queue.stream()).mapToInt(Integer::intValue).toArray();
При этом используется reverse
утилита, предложенная Стюартом Марксом в этом ответе, такая что:
@SuppressWarnings("unchecked")
static <T> Stream<T> reverse(Stream<T> input) {
Object[] temp = input.toArray();
return (Stream<T>) IntStream.range(0, temp.length)
.mapToObj(i -> temp[temp.length - i - 1]);
}
Ответ 4
В версии Java8 вы можете использовать Stream API, чтобы помочь вам.
Скелет кода вроде этого:
int[] reversedQueue = queue.stream()
.collect(Collector.of(() -> new ArrayDeque<Integer>(), ArrayDeque::addFirst, (a,b)->a))
.stream().mapToInt(Integer::intValue).toArray();
Ответ 5
Наконец, я выясняю это решение в одну строку.
Integer[] intArray = queue.stream()
.collect(LinkedList::new, LinkedList::addFirst, LinkedList::addAll)
.toArray(new Integer[queue.size()]);
версия int[]
должна понравиться
int[] intArray = queue.stream()
.collect(LinkedList<Integer>::new, LinkedList::addFirst, LinkedList::addAll)
.stream()
.mapToInt(Integer::intValue)
.toArray();
Ответ 6
Вы можете использовать утилиту LazyIterate
из Eclipse Collections следующим образом.
int[] res = LazyIterate.adapt(queue)
.collectInt(i -> i)
.toList()
.asReversed()
.toArray();
Вы также можете использовать класс Collectors2
с потоком Java.
int[] ints = queue.stream()
.collect(Collectors2.collectInt(i -> i, IntLists.mutable::empty))
.asReversed()
.toArray();
Вы можете MutableIntList
значения int
непосредственно в MutableIntList
, обратить его обратно, а затем преобразовать в массив int
.
int[] ints =
IntLists.mutable.ofAll(queue.stream().mapToInt(i -> i)).asReversed().toArray();
Наконец, вы можете MutableIntStack
значения int
непосредственно в MutableIntStack
и преобразовать его в массив int
.
int[] ints =
IntStacks.mutable.ofAll(queue.stream().mapToInt(i -> i)).toArray();
Примечание: я являюсь коммиттером для Eclipse Collections.
Ответ 7
Это одна строка, но она может быть не очень эффективной:
int[] res = queue.stream()
.collect(LinkedList<Integer>::new, (l, e) -> l.addFirst(e), (l1, l2) -> l1.addAll(l2))
.stream()
.mapToInt(Integer::intValue)
.toArray();
Если вы хотите быть эффективным и читабельным, вы должны продолжать использовать то, что у вас есть сейчас.
Ответ 8
Вот другое решение, использующее Stream
и Collections.reverse()
в одной строке кода:
Integer[] reversedArray = queue.stream()
.collect(Collectors.collectingAndThen(Collectors.toList(),
list -> {
Collections.reverse(list);
return list.toArray(new Integer[0]);
}
));
ИЛИ ЖЕ
int[] reversedArray = queue.stream()
.collect(Collectors.collectingAndThen(Collectors.toList(),
list -> {
Collections.reverse(list);
return list.stream()
.mapToInt(Integer::intValue)
.toArray();
}
));
Ответ 9
Вот способ, который создает обращенный массив без обращения к очереди:
int[] i = { queue.size() };
int[] array = new int[i[0]];
queue.forEach(n -> array[--i[0]] = n);
Приведенный выше код довольно хакерский из-за невозможности изменить локальные переменные из лямбда-выражений. Поэтому здесь i
должен быть массивом из одного элемента, чтобы преодолеть это ограничение.
Примечание: имейте ввиду, что я пришел к этому решению просто ради удовольствия :)