Обращение очереди <Integer>и преобразование ее в массив int - PullRequest
0 голосов
/ 04 января 2019

У меня есть 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 обращенных элементов - вот что мне нужно.

Ответы [ 9 ]

0 голосов
/ 04 января 2019

Вот другое решение с использованием 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();
                }
        ));
0 голосов
/ 05 января 2019

Вот способ создания обращенного массива без обращения к очереди:

int[] i = { queue.size() };
int[] array = new int[i[0]];
queue.forEach(n -> array[--i[0]] = n);

Приведенный выше код довольно хакерский из-за невозможности изменять локальные переменные из лямбда-выражений.Так что здесь i должен быть массив из одного элемента, чтобы преодолеть это ограничение.

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

0 голосов
/ 04 января 2019

Вы можете использовать утилиту LazyIterate из Eclipse Collections следующим образом.

int[] res = LazyIterate.adapt(queue)
        .collectInt(i -> i)
        .toList()
        .asReversed()
        .toArray();

Вы также можете использовать Collectors2*Класс 1011 * с потоком Java.

int[] ints = queue.stream()
        .collect(Collectors2.collectInt(i -> i, IntLists.mutable::empty))
        .asReversed()
        .toArray();

Вы можете направить значения int непосредственно в MutableIntList, обратить его обратно, а затем преобразовать в intмассив.

int[] ints =
    IntLists.mutable.ofAll(queue.stream().mapToInt(i -> i)).asReversed().toArray();

Наконец, вы можете направить значения int непосредственно в MutableIntStack и преобразовать его в массив int.

int[] ints =
    IntStacks.mutable.ofAll(queue.stream().mapToInt(i -> i)).toArray();

Примечание. Я являюсь коммиттером для коллекций Eclipse.

0 голосов
/ 04 января 2019

Здесь не нужно фантазировать.

static int[] toReversedArray(Queue<Integer> queue) {
    int i = queue.size();
    int[] array = new int[i];
    for (int element : queue) {
        array[--i] = element;
    }
    return array;
}

Не однострочный, но легко читаемый и быстрый.

0 голосов
/ 04 января 2019

В Java8 версии вы можете использовать Stream API , чтобы помочь вам.

Скелет кода, подобный этому:

int[] reversedQueue = queue.stream()
    .collect(Collector.of(() -> new ArrayDeque<Integer>(), ArrayDeque::addFirst, (a,b)->a))
    .stream().mapToInt(Integer::intValue).toArray();
0 голосов
/ 04 января 2019

Это одна строка, но она может быть не очень эффективной:

int[] res = queue.stream()
                 .collect(LinkedList<Integer>::new, (l, e) -> l.addFirst(e), (l1, l2) -> l1.addAll(l2))
                 .stream()
                 .mapToInt(Integer::intValue)
                 .toArray();

Если вы хотите быть эффективными и удобочитаемыми, вы должны продолжать использовать то, что у вас есть сейчас.

0 голосов
/ 04 января 2019

Наконец, я разобрался с этим решением в одну строку.

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();
0 голосов
/ 04 января 2019

Во-первых, , пожалуйста не используйте необработанные типы ( до используйте оператор алмазов).Не совсем один вкладыш, но вы могли бы сначала преобразовать в int[], а затем использовать обыкновенные 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());
0 голосов
/ 04 января 2019

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]);
}
...