web-dev-qa-db-ja.com

Javaでリンクリストの配列を作成できません...?

私は、行列の値を格納するためにLinkedListの配列を使用するneedsというスパース行列クラスに取り組んでいます。配列の各要素(各LinkedList)は、行列の行を表します。また、LinkedList配列の各要素は列と格納された値を表します。

私のクラスでは、次のような配列の宣言があります。

private LinkedList<IntegerNode>[] myMatrix;

そして、SparseMatrixのコンストラクターで、以下を定義しようとします:

myMatrix = new LinkedList<IntegerNode>[numRows];

私が得ることになったエラーは

LinkedList<IntegerNode>の汎用配列を作成できません。

したがって、これには2つの問題があります。

  1. 私は何を間違えていますか?
  2. 配列を作成できない場合、配列の宣言で型が受け入れられるのはなぜですか?

IntegerNodeは私が作成したクラスです。そして、私のクラスファイルはすべて一緒にパッケージ化されています。

99
kafuchau

汎用配列の作成は使用できません。これは、Java generics。

警告なしの方法は次のとおりです。

  1. リストの配列の代わりにリストのリストを使用する:

    List< List<IntegerNode>> nodeLists = new LinkedList< List< IntegerNode >>();
    
  2. リストの配列の特別なクラスの宣言:

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

何らかの理由で、型をキャストし、次のように宣言する必要があります。

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

構文の問題は別として、配列とリンクリストを使用して行列を表すのは奇妙に思えます。マトリックスの任意のセルにアクセスできるようにするには、おそらく実際の配列または少なくともArrayListが行を保持する必要があります。LinkedListは最初の要素からリスト全体を横断する必要があるためArrayListまたは実際の配列を使用した非常に高速のO(n)とは対照的な、特定の要素、O(1)操作。

ただし、このマトリックスはスパースであると述べたので、おそらくデータを格納するより良い方法は、マップのマップとしてです。最初のマップのキーは行インデックスを表し、その値はキーが列インデックスである行マップです、値は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にできます。これは、インデックス順で列をトラバースする場合と同じですが、これらのケースが必要ない場合は、HashMapTreeMapよりも高速です。もちろん、設定されていないnull値を処理する任意のセルを取得および設定するヘルパーメソッドは便利です。

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

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

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

警告なしでコンパイルします。

見た目は悪くありませんか?

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

リストの配列が必要です。1つの選択肢は以下を試すことです:

_private IntegerNode[] node_array = new IntegerNode[sizeOfYourChoice];
_

次に、_node_array[i]_は、_ArrayList<IntegerNode>_または_LinkedList<IntegerNode>_(好きなリストの実装が何であれ)のhead(first)ノードを格納します。

この設計では、ランダムアクセスメソッドlist.get(index)は失われますが、タイプセーフ配列のヘッド/フィストノードストアからリストを走査することができます。

これは、ユースケースによっては許容できる設計の選択肢になる場合があります。たとえば、この設計を使用してグラフの隣接リストを表します。ほとんどのユースケースでは、リスト内の頂点にランダムにアクセスするのではなく、特定の頂点について隣接リストを走査する必要があります。

0
Yiling

次の操作を行うと、問題のエラーメッセージが表示されます

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

しかし、宣言からリストタイプを削除するだけで、目的の機能が得られるようです。

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

これらの2つの宣言は、私が知らない方法で大幅に異なりますか?

[〜#〜] edit [〜#〜]

ああ、私は今この問題に遭遇したと思います。

Forループで行列を反復処理し、リストを初期化するとうまくいくようです。ただし、提供されている他のソリューションのいくつかほど理想的ではありません。

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

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