it-swarm.com.ru

Не удается создать массив связанных списков в Java ...?

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

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

private LinkedList<IntegerNode>[] myMatrix;

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

myMatrix = new LinkedList<IntegerNode>[numRows];

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

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

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

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

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

98
kafuchau

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

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

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

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

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

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

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

Помимо проблем с синтаксисом, мне кажется странным использовать массив и связанный список для представления матрицы. Чтобы иметь возможность доступа к произвольным ячейкам матрицы, вам, вероятно, понадобится фактический массив или хотя бы 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. Конечно, были бы полезны вспомогательные методы для получения и установки произвольной ячейки, обрабатывающие неустановленные нулевые значения.

5
Dov Wasserman
class IntegerNodeList extends LinkedList<IntegerNode> {}

IntegerNodeList[] myMatrix = new IntegerNodeList[numRows]; 
4
Bob

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];

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

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

3
user306708

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

2
Paul Croarkin
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
Andrii

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

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

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

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

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

0
Yiling

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

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

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

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

Эти две декларации кардинально отличаются от того, о чем я не знаю?

РЕДАКТИРОВАТЬ

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

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

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

    matrix[i] = new LinkedList<>();
}
0
Ryan