Обращение очереди <Integer> и преобразование ее в массив int

У меня есть Queue<Integer> объявленная как Queue<Integer> queue=new LinkedList(); Мне нужно изменить порядок элементов в нем, а затем преобразовать его в массив int. Я написал ниже код:

Collections.reverse((List)queue);
int[] res=queue.stream().mapToInt(Integer::intValue).toArray();

Этот код имеет две проблемы:

  1. очередь на явное приведение (List)queue;
  2. Интересно, есть ли однострочное решение?

Так есть ли у нас более элегантный способ сделать это?


Уточнение проблемы:

Является ли очередь перевернутой, не важно. Множество 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 должен быть массивом из одного элемента, чтобы преодолеть это ограничение.

Примечание: имейте ввиду, что я пришел к этому решению просто ради удовольствия :)