Я как-то наткнулся на требование создать массив PriorityQueues. Обходным путем может быть создание HashMap, но я предпочел массив.
Я объявил массив приоритетных очередей следующим образом.
PriorityQueue<long[]>[] arr = new PriorityQueue[10];
Я хотел, чтобы каждая приоритетная очередь в arr
имела одну и ту же функцию сравнения, которая сортирует элементы в PriorityQueue<long[]>
в порядке второго элемента внутри long[]
.
Я попытался заполнить массив arr
с помощью.
Arrays.fill(arr, new PriorityQueue<>(new Comparator<>(){
public int compare(int[] a, int[] b){
return b[1] - a[1];
}
}));
Но это дает мне ошибку, может ли кто-нибудь помочь, что не так с этим подходом?
Код:
import java.util.*;
public class Main
{
public static void main(String[] args) {
PriorityQueue<long[]>[] arr = new PriorityQueue[10];
Arrays.fill(arr, new PriorityQueue<>(new Comparator<>(){
public int compare(int[] a, int[] b){
return b[1] - a[1];
}
}));
}
}
Ошибка:
Main.java:12: error: <anonymous Main$1> is not abstract and does not override abstract method compare(Object,Object) in Comparator
Arrays.fill(arr, new PriorityQueue<>(new Comparator<>(){
^
Main.java:13: error: method does not override or implement a method from a supertype
public int compare(int[] a, int[] b){
^
(due to <>, every non-private method declared in this anonymous class must override or implement a method from a supertype)
Также есть ли лучший способ назначить объект каждому элементу массива во время объявления?
Я добавил ошибку и полный код. Не могли бы вы объяснить, что именно вызывает эту ошибку?
Чтобы создать объект с компаратором, вы можете использовать этот подход:
PriorityQueue<Long[]> pq = new PriorityQueue<>(new Comparator<Long[]>() {
public int compare(Long[] a, Long[] b) {
return a[1].compareTo(b[1]);
}
});
Но обратите внимание, что я использовал Long
, а не long
, и это позволяет мне также использовать compareTo
вместо вычитания, чтобы гарантировать, что вы не столкнетесь с неожиданными результатами, выходящими за границы для возвращаемого значения Compare
int
.
В приведенном выше примере используется подход анонимного внутреннего класса, который вы хотели использовать в своем вопросе, но обратите внимание также на явный тип Comparator<Long[]>
.
В качестве необязательного дополнительного шага это можно упростить, заменив внутренний класс лямбда-выражением:
PriorityQueue<Long[]> pq = new PriorityQueue<>((Long[] a, Long[] b) -> a[1].compareTo(b[1]));
Поэтому вы можете использовать любой из вышеперечисленных подходов в своем Arrays.fill
.
Вот лямбда-подход:
PriorityQueue<long[]>[] arr = new PriorityQueue[10];
Arrays.fill(arr, new PriorityQueue<>((Long[] a, Long[] b) -> a[1].compareTo(b[1])));
Просто отметим - этот компаратор может быть только искусственным примером для этого вопроса, но он немного необычен. И мне было интересно, действительно ли вы хотели вместо этого сравнить a[0]
с b[0]
.
И, очевидно, все очереди в этот момент пусты.
Обновлять
Полностью согласен с комментарием от @OldDogProgrammer. Смешивать дженерики и массивы таким образом не рекомендуется. «Предпочитайте списки массивам» — Джош Блох, «Эффективная Java».
Обновление 2
Вы спросили, могу ли я:
предоставить некоторые ссылки или некоторые материалы для чтения
Вот почему я упомянул Джоша Блоха и «Эффективную Java». Вы можете выполнить онлайн-поиск по запросу «предпочесть списки массивам josh bloch», чтобы увидеть различные статьи, в которых подробно обсуждается эта тема.
Вы спрашивали:
что вызывает ошибку здесь?
Вы не указали конкретный тип для new Comparator<>()
.
Вот почему я упомянул «обратите внимание также на явный тип Comparator<Long[]>
» в своем ответе (см. Выше).
Объекты, которые вы хотите, чтобы компаратор сравнивал, являются Long[]
массивами, но вы указали int[]
в своей реализации:
compare(int[] a, int[] b)
Вы вообще не указали тип в своем конструкторе new Comparator<>()
, поэтому по умолчанию он равен compare(Object,Object)
, что вы можете увидеть в сообщении об ошибке.
Таким образом, существует также несоответствие между конструктором и предоставленной вами реализацией, а также несоответствие между конструктором и тем, что вы должны были предоставить в реализации.
На самом деле это еще одна тема Джоша Блоха:
Отдавайте предпочтение универсальным типам.
На эту тему также есть отличные статьи в Интернете. Я ожидаю, что есть также несколько отличных ответов на переполнение стека по этому поводу и «Предпочитать списки массивам».
Вы также можете искать термины ковариантный и инвариантный в контексте дженериков и массивов Java в качестве другой темы исследования.
Не могли бы вы предоставить справку или материал для чтения о том, почему «Смешивание дженериков и массивов» не рекомендуется? Также я обновил вопрос, не могли бы вы объяснить, что здесь вызывает ошибку? Я пытаюсь заполнить массив новым объектом PriorityQueue, в котором я передал объект сравнения для каждого объекта PQ в массиве. Какую ошибку я делаю?
ОК - я добавил несколько примечаний к своему ответу - надеюсь, они помогут. Это большие (и важные) темы, поэтому я попытался предоставить некоторые указатели для дальнейшего изучения.
Спасибо за ваше время, это многое проясняет для меня.
Является ли одно из сообщений об ошибке сообщением об ошибке компилятора «создание общего массива»? Те, кто обновляет Java, решили реализовать дженерики таким образом, что они несовместимы с массивами. Вы можете попробовать что-то вроде
List<PriorityQueue<long[]>> arr = new ArrayList<>();