Java에서 LinkedLists 배열을 만들 수 없습니까?


102

나는 희소 행렬 클래스에서 일하고 있어요 필요 의 배열을 사용하는 LinkedList행렬의 값을 저장합니다. 배열의 각 요소 (즉, 각 LinkedList)는 행렬의 행을 나타냅니다. 그리고 LinkedList배열의 각 요소 는 열과 저장된 값을 나타냅니다.

내 수업에는 다음과 같이 배열 선언이 있습니다.

private LinkedList<IntegerNode>[] myMatrix;

그리고에 대한 생성자에서 다음 SparseMatrix을 정의하려고합니다.

myMatrix = new LinkedList<IntegerNode>[numRows];

내가 결국 얻는 오류는

의 일반 배열을 만들 수 없습니다 LinkedList<IntegerNode>.

그래서 두 가지 문제가 있습니다.

  1. 내가 뭘 잘못하고 있고
  2. 배열을 만들 수없는 경우 배열 선언에서 유형이 허용되는 이유는 무엇입니까?

IntegerNode내가 만든 클래스입니다. 그리고 모든 클래스 파일이 함께 패키지화됩니다.

답변:


64

일반 배열 생성을 사용할 수 없습니다. 그것은 자바 제네릭의 결함 / 특징입니다.

경고가없는 방법은 다음과 같습니다.

  1. 목록 배열 대신 목록 목록 사용 :

    List< List<IntegerNode>> nodeLists = new LinkedList< List< IntegerNode >>();
  2. 목록 배열에 대한 특수 클래스 선언 :

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

19
후자의 솔루션에 대한 더 나은 대안은 다음과 같습니다. class IntegerNodeList extends List<IntegerNode> {}
kamasheto

이 구현은 엄청나게 느립니다. [1000] [2000] 요소 (nodeLists.get (1000) .get (2000))를 가져 오면 LinkedList가 3000 번 반복됩니다! 누군가 인덱싱 할 수있는 경우 LinkedList를 피하십시오. ArrayList는 더 빠르게 인덱싱되지만 Fredrik의 솔루션이 전반적으로 더 좋습니다.
Steve Zobell 2017 년

142

어떤 이유로 유형을 캐스팅하고 다음과 같이 선언해야합니다.

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

비슷한 문제를 조사한 결과 위의 캐스트가 컬렉션 프레임 워크 전체에서 사용되는 매우 일반적인 '해킹'이라는 것을 읽었습니다.
luke

15
IMO, 이것이 선택된 대답이어야합니다. 나는 실험 해본 적이 없지만, Sergey의 # 2 방법이 상당한 오버 헤드를 만들어 낸다는 직감이 있습니다. 그리고 나는 # 1이하는 것이 긍정적이다. 목록은 여러 가지 측면에서 배열만큼 효율적이지는 않지만 여기서 자세히 설명하지는 않지만 배열과 비교하여 목록을 사용할 때 실험을 수행하고 큰 속도 저하를 보았습니다. 목록에 항목을 추가하는 것보다 자신의 배열을 관리하고 재 할당하는 것이 더 빠릅니다.
Ricket


4
여전히 "유형 안전성 : 확인되지 않은 캐스트"경고가 표시됩니다. Bob의 솔루션은 나에게 가장 깨끗해 보입니다.
Marco Lackovic

3
JDK 7에서 위의 내용은 rawtypes 경고를 제공합니다. 제한되지 않은 <?> 유형을 사용하여 해결할 수 있지만 여전히 확인되지 않은 경고 (억제 할 수 있음)가 표시됩니다. 예 : <br> <code> myMatrix = (LinkedList <IntegerNode> []) new LinkedList <?> [numRows]; </ code>
Neon

5

구문 문제를 제외하고는 배열과 연결 목록을 사용하여 행렬을 나타내는 것이 이상하게 보입니다. 행렬의 액세스 임의의 세포 수 있으려면, 당신은 실제 배열을 원하는 아마 것 또는 적어도이 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. 물론 임의의 셀을 가져오고 설정하고 설정되지 않은 null 값을 처리하는 도우미 메서드가 유용합니다.


4
class IntegerNodeList extends LinkedList<IntegerNode> {}

IntegerNodeList[] myMatrix = new IntegerNodeList[numRows]; 

LinkedList의 제네릭을 놓쳤습니다.
Peter Wippermann

3

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

경고없이 컴파일됩니다.

너무 나쁘게 보이지 않습니까?


IntegerNodeList : 어떤 클래스와 함께 사용 하시겠습니까? 예를 들어 ArrayList <IntegerNode>를 할당 할 수 없습니다. ArrayList도 확장해야합니다 ...
Hans-Peter Störr 2010

배열 초기화 외부에서 IntegerNodeList 인터페이스를 사용할 필요가 없습니다. List <IntegerNode> [] myMatrix = new IntegerNodeList [5]; for (int i = 0; i <myMatrix.length; i ++) {myMatrix [i] = new ArrayList <IntegerNode> (); }
user306708

1
List<IntegerNode>[] myMatrix = new IntegerNodeList[numRows];이것은 미묘하지만 중요한 문제가 있습니다. 배열 에만 넣을 수 있습니다 IntegerNodeList. myMatrix[i] = new ArrayList<IntegerNode>();던질 것 ArrayStoreException입니다.
Radiodef 2011

2
List<String>[] lst = new List[2];
lst[0] = new LinkedList<String>();
lst[1] = new LinkedList<String>();

경고가 없습니다. NetBeans 6.9.1, jdk1.6.0_24


1
사실 경고는 없지만 Oracle의 Java SE 6 Update 32에서는 "The type List is not generic; it cannot be parameterized with arguments <String>"라는 컴파일 오류가 발생합니다. <문자열> 인수를 제거하면 "유형 불일치 : LinkedList <문자열>에서 목록으로 변환 할 수 없습니다"라는 또 다른 오류가 생성됩니다.
Marco Lackovic


0

다음을 수행하면 문제의 오류 메시지가 나타납니다.

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

List 배열이 필요합니다. 한 가지 대안은 다음을 시도하는 것입니다.

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

그런 다음 또는 (좋아하는 목록 구현) node_array[i]의 헤드 (첫 번째) 노드를 저장합니다 . ArrayList<IntegerNode>LinkedList<IntegerNode>

이 디자인에서는 임의 액세스 방법을 잃게 list.get(index)되지만 유형 안전 배열의 head / fist 노드 저장소로 시작하는 목록을 계속 탐색 할 수 있습니다.

이는 사용 사례에 따라 허용되는 디자인 선택 일 수 있습니다. 예를 들어,이 디자인을 사용하여 그래프의 인접 목록을 나타내며, 대부분의 사용 사례에서 목록의 일부 정점에 임의로 액세스하는 대신 주어진 정점에 대해 인접 목록을 탐색해야합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.