Не удается создать массив LinkedLists в Java...?
Я работаю над разреженным матричным классом, которому требуется, чтобы использовать массив LinkedList
для хранения значений матрицы. Каждый элемент массива (т.е. Каждый LinkedList
) представляет собой строку матрицы. И каждый элемент массива LinkedList
представляет столбец и сохраненное значение.
В моем классе у меня есть объявление массива как:
private LinkedList<IntegerNode>[] myMatrix;
И, в моем конструкторе для SparseMatrix
, я пытаюсь определить:
myMatrix = new LinkedList<IntegerNode>[numRows];
Ошибка, которую я получаю, составляет
Невозможно создать общий массив LinkedList<IntegerNode>
.
Итак, у меня есть две проблемы:
- Что я делаю неправильно, и
- Почему допустимый тип объявления для массива, если он не может быть создан?
IntegerNode
- это класс, который я создал. И все мои файлы классов упакованы вместе.
Ответы
Ответ 1
Вы не можете использовать создание общего массива. Это недостаток дженериков java.
Способы без предупреждений:
-
Использование списка списков вместо массива списков:
List< List<IntegerNode>> nodeLists = new LinkedList< List< IntegerNode >>();
-
Объявление специального класса для массива списков:
class IntegerNodeList {
private final List< IntegerNode > nodes;
}
Ответ 2
По какой-то причине вам нужно указать тип и сделать объявление следующим образом:
myMatrix = (LinkedList<IntegerNode>[]) new LinkedList<?>[numRows];
Ответ 3
Помимо проблем с синтаксисом, мне кажется странным использовать массив и связанный список для представления матрицы. Чтобы иметь доступ к произвольным ячейкам матрицы, вам, вероятно, понадобится фактический массив или, как минимум, ArrayList
для хранения строк, поскольку LinkedList
должен пересечь весь список из первого элемента в какой-либо конкретный элемент, O(n)
, а не намного быстрее O(1)
с ArrayList
или фактическим массивом.
Поскольку вы упомянули, что эта матрица разрежена, хотя, возможно, лучший способ хранения данных - это карта карт, где ключ на первой карте представляет собой индекс строки, а его значение представляет собой карту строк, ключи которой индекс столбца со значением, являющимся вашим классом IntegerNode. Таким образом:
private Map<Integer, Map<Integer, IntegerNode>> myMatrix = new HashMap<Integer, Map<Integer, IntegerNode>>();
// access a matrix cell:
int rowIdx = 100;
int colIdx = 30;
Map<Integer, IntegerNode> row = myMatrix.get(rowIdx); // if null, create and add to matrix
IntegerNode node = row.get(colIdx); // possibly null
Если вам нужно пройти по строке по строке, вы можете сделать тип карты строк TreeMap
, а также для перемещения столбцов в индексном порядке, но если вам не нужны эти случаи, HashMap
быстрее, чем TreeMap
. Разумеется, полезны методы-помощники для получения и установки произвольной ячейки, обрабатывающие ненулевые значения.
Ответ 4
myMatrix = (LinkedList<IntegerNode>[]) new LinkedList[numRows];
литье этого способа работает, но все же оставляет вам неприятное предупреждение:
"Тип безопасности: выражение типа List [] требует необработанного преобразования.."
Объявление специального класса для массива списков:
class IntegerNodeList { private final List< IntegerNode > nodes; }
- умная идея, чтобы избежать предупреждения. возможно, немного лучше использовать интерфейс для него:
public interface IntegerNodeList extends List<IntegerNode> {}
затем
List<IntegerNode>[] myMatrix = new IntegerNodeList[numRows];
компилируется без предупреждений.
не выглядит слишком плохо, не так ли?
Ответ 5
class IntegerNodeList extends LinkedList<IntegerNode> {}
IntegerNodeList[] myMatrix = new IntegerNodeList[numRows];
Ответ 6
В Java 1.5 нет генераторного массива (или 1.6, насколько я могу судить). См. https://community.oracle.com/message/4829402.
Ответ 7
List<String>[] lst = new List[2];
lst[0] = new LinkedList<String>();
lst[1] = new LinkedList<String>();
Никаких предупреждений. NetBeans 6.9.1, jdk1.6.0_24
Ответ 8
Если я сделаю следующее, я получаю соответствующее сообщение об ошибке
LinkedList<Node>[] matrix = new LinkedList<Node>[5];
Но если я просто удалю тип списка в объявлении, он, кажется, имеет желаемую функциональность.
LinkedList<Node>[] matrix = new LinkedList[5];
Являются ли эти два объявления радикально разными, каким образом я не знаю?
ИЗМЕНИТЬ
А, думаю, я столкнулся с этой проблемой сейчас.
Итерация по матрице и инициализация списков в for-loop, похоже, сработают. Хотя это не так идеально, как некоторые другие предлагаемые решения.
for(int i=0; i < matrix.length; i++){
matrix[i] = new LinkedList<>();
}
Ответ 9
Вам нужен массив List, один из вариантов - попробовать:
private IntegerNode[] node_array = new IntegerNode[sizeOfYourChoice];
Затем node_array[i]
хранит головку (первая) node ArrayList<IntegerNode>
или LinkedList<IntegerNode>
(независимо от вашей избранной реализации списка).
В соответствии с этой конструкцией вы потеряете метод произвольного доступа list.get(index)
, но затем вы можете по-прежнему перемещаться по списку, начиная с хранилища head/fist node в безопасном массиве типов.
Это может быть приемлемым выбором дизайна в зависимости от вашего варианта использования. Например, я использую этот проект для представления списка граф смежности в большинстве случаев использования, для этого требуется переместить список смежности в любом случае для данной вершины вместо случайного доступа к некоторой вершине в списке.