Не удается создать массив LinkedLists в Java ...? - PullRequest
98 голосов
/ 20 октября 2008

Я работаю над классом разреженной матрицы, которому нужно , чтобы использовать массив LinkedList для хранения значений матрицы. Каждый элемент массива (то есть каждый LinkedList) представляет строку матрицы. И каждый элемент в массиве LinkedList представляет столбец и сохраненное значение.

В моем классе у меня есть объявление массива как:

private LinkedList<IntegerNode>[] myMatrix;

И в моем конструкторе для SparseMatrix я пытаюсь определить:

myMatrix = new LinkedList<IntegerNode>[numRows];

Я получаю ошибку

Невозможно создать универсальный массив LinkedList<IntegerNode>.

Итак, у меня есть две проблемы с этим:

  1. Что я делаю не так, и
  2. Почему тип допустим в объявлении для массива, если он не может быть создан?

IntegerNode - это класс, который я создал. И все мои файлы классов упакованы вместе.

Ответы [ 9 ]

138 голосов
/ 20 октября 2008

По какой-то причине вы должны привести тип и сделать объявление следующим образом:

myMatrix = (LinkedList<IntegerNode>[]) new LinkedList<?>[numRows];
64 голосов
/ 20 октября 2008

Вы не можете использовать создание универсального массива. Это недостаток / особенность java дженериков.

Способы без предупреждений:

  1. Использование списка списков вместо массива списков:

    List< List<IntegerNode>> nodeLists = new LinkedList< List< IntegerNode >>();
    
  2. Объявление специального класса для массива списков:

    class IntegerNodeList {
        private final List< IntegerNode > nodes;
    }
    
5 голосов
/ 20 октября 2008

Помимо проблем с синтаксисом, мне кажется странным использовать массив и связанный список для представления матрицы. Чтобы иметь возможность доступа к произвольным ячейкам матрицы, вы, вероятно, захотите, чтобы фактический массив или по крайней мере 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 голосов
/ 29 марта 2011
class IntegerNodeList extends LinkedList<IntegerNode> {}

IntegerNodeList[] myMatrix = new IntegerNodeList[numRows]; 
3 голосов
/ 01 апреля 2010

myMatrix = (LinkedList<IntegerNode>[]) new LinkedList[numRows];

применение этого способа работает, но все равно оставляет вам неприятное предупреждение:

"Безопасность типов: выражение типа List [] нуждается в непроверенном преобразовании .."

Объявление специального класса для Array of Lists:

class IntegerNodeList { private final List< IntegerNode > nodes; }

- это умная идея, чтобы избежать предупреждения. может быть, немного лучше использовать для этого интерфейс:

public interface IntegerNodeList extends List<IntegerNode> {}

тогда

List<IntegerNode>[] myMatrix = new IntegerNodeList[numRows];

компилируется без предупреждений.

выглядит не так уж плохо, не так ли?

2 голосов
/ 30 апреля 2011
List<String>[] lst = new List[2];
lst[0] = new LinkedList<String>();
lst[1] = new LinkedList<String>();

Никаких предупреждений. NetBeans 6.9.1, jdk1.6.0_24

2 голосов
/ 20 октября 2008

В Java 1.5 нет создания универсального массива (или, насколько я могу судить, 1.6). Смотри https://community.oracle.com/message/4829402.

0 голосов
/ 10 февраля 2013

Вам нужен массив List, можно попробовать:

private IntegerNode[] node_array = new IntegerNode[sizeOfYourChoice];

Затем node_array[i] сохраняет головной (первый) узел ArrayList<IntegerNode> или LinkedList<IntegerNode> (независимо от вашей реализации списка избранного).

При такой схеме вы теряете метод произвольного доступа list.get(index), но тогда вы все равно можете просматривать список, начиная с хранилища узлов / кулаков в массиве типа safe.

Это может быть приемлемым выбором дизайна в зависимости от вашего варианта использования. Например, я использую этот дизайн для представления списка смежности графа, в большинстве случаев он требует обхода списка смежности в любом случае для данной вершины вместо произвольного доступа к какой-либо вершине в списке.

0 голосов
/ 04 октября 2012

Если я сделаю следующее, я получу сообщение об ошибке

LinkedList<Node>[] matrix = new LinkedList<Node>[5];

Но если я просто удаляю тип списка в объявлении, он, похоже, обладает желаемой функциональностью.

LinkedList<Node>[] matrix = new LinkedList[5];

Значительно ли отличаются эти две декларации, о которых я не знаю?

EDIT

Ах, я думаю, что столкнулся с этой проблемой сейчас.

Кажется, работает перебор матрицы и инициализация списков в цикле for. Хотя он не так идеален, как другие предлагаемые решения.

for(int i=0; i < matrix.length; i++){

    matrix[i] = new LinkedList<>();
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...