2011-10-13 2 views
15

,의는 다음과 같이 가정 해 봅시다 :자바에서 반복자를 복제 하시겠습니까? 나는 플레이어의 목록을 가지고 게임에

LinkedList<String> players = new LinkedList<String>(); 

을 나는 각각의 플레이어가 다른 플레이어의 각각 상호 작용할 수 있도록하려면, 그래서 두 개의 중첩 루프 쓰기 :

Iterator<String> i1 = players.iterator(); 
while (i1.hasNext()) { 
    String p1 = i1.next(); 
    Iterator<String> i2 = players.iterator(); 
    // But I want to do this: Iterator<String> i2 = i1.clone(); 
    while (i2.hasNext()) { 
     String p2 = i2.next(); 
     System.out.println("Interact: " + p1 + ", " + p2); 
    } 
} 

각 플레이어 쌍이 한 번만 상호 작용하기를 원하기 때문에 바깥 쪽 루프의 현재 플레이어 다음에 플레이어와 함께 안쪽 루프를 시작하고 싶습니다. 그래서 반복자를 복제하고 싶지만 컴파일되지 않습니다.

대신 무엇을해야합니까?

+3

대신 'ArrayList '을 사용하지 않으시겠습니까? 위치를 사용하는 알고리즘은 해당 데이터 구조에서 사소한 것입니다. –

+0

그러면 A와 A가 페어링되지 않을까요? –

+0

@Kirk : 예, ArrayList가 작동하지만 목록의 중간에 플레이어를 삽입하고 제거해야 할 수도 있기 때문에 LinkedList를 원합니다. –

답변

25

다음은 그것을 할 것입니다 :

그것은 ListIterator의 능력 지정된 위치에서 시작하고 또한 그것의 현재 위치를 알고에 의존
ListIterator<String> i1 = players.listIterator(0); 
while (i1.hasNext()) { 
    String p1 = i1.next(); 
    ListIterator<String> i2 = players.listIterator(i1.nextIndex()); 
    while (i2.hasNext()) { 
     String p2 = i2.next(); 
     System.out.println("Interact: " + p1 + ", " + p2); 
    } 
} 

.

+1

aix가 다시 나타납니다. +1, 아름다운 솔루션. – aioobe

+0

감사합니다. 그러나, 한 가지 질문 : listIterator (int) 메서드는 어떻게 작동합니까? 목록의 맨 앞에서 시작하지 않고 지정된 위치로 반복합니다. 그렇습니까? –

+3

@ ThomasPadron-McCarthy : 인터페이스의 일부로 지정되지 않았습니다. 그러나 연결된 목록의 특성을 고려할 때 거의 확실합니다. 다른 한편으로, 나는 이것을 피할 수있는 해결책을 모르고있다. – NPE

2

aix answer 외에도 특정 인덱스에서 시작하는 반복기를 만들면 선형 연산으로 바인딩된다는 것을 지적하고 싶습니다. 그것이 아니라면, 당신은 모순 될

elementN = createIterator(linkedList, N).next(); 

사용하여 일정 시간의 목록에 임의 접근을 할 수있을 것입니다.

상황에서

그래서 저는이 여전히 AIX에 의한 솔루션과 같은 복잡한 것으로, 가장 효율적인 솔루션이 실제로 그러나

List<String> tmp = new ArrayList<String>(players); 
for (int p1 = 0; p1 < tmp.size(); p1++) 
    for (int p2 = p1+1; p2 < tmp.size(); p2++) 
     System.out.println("Interact: " + tmp.get(p1) + ", " + tmp.get(p2)); 

참고 할 것이라고 믿는다 O (n)하지만 더 작은 상수 계수가있을 수 있습니다.

+1

나는 동의하지 않습니다. 원하는 인덱스를 가리키는 반복자가 있으면 인터페이스가 허용하는 한 즉시 해당 인덱스를 가져올 수 있어야합니다. 이 상상의''i1.clone()'메서드는'O (1)'이고'players.listIterator (i1.nextIndex())'는'O (n)'입니다. 'clone()'메소드는 복제 된 iterator에 현재 보유하고있는 노드를 제공하여 목록의 해당 지점까지 반복 할 필요가 없도록합니다. – anthropomorphic

+0

원칙적으로 당신이 옳습니다. 상상의 복제 방법은 구현하기가 쉽지 않습니다. 그러나이 경우 OP는 복제를 지원하지 않는 java.util.LinkedList를 참조했을 가능성이 큽니다. 이 주제에 대해 많은 질문이 있습니다. 예를 들어 http://stackoverflow.com/questions/5963399/how-can-i-make-a-copy-of-aniterator-in-java – aioobe

0

listIterator(int) (NPE의 답)과 관련된 선형 비용을 피할 수있는 해결책은 내 answer to a similar question을 참조하십시오. 요약하면,리스트가 방문한 순서에 신경 쓰지 않는 한, 마지막 요소에서 외부 루프를 시작하여 뒤로 반복하고 첫 번째 요소에서 내부 루프를 시작하고 두 반복기가 반복 될 때까지 앞으로 반복 할 수 있습니다 만나다. list가 LinkedList, 즉 이중 연결리스트이기 때문에 list.listIterator (list.size())에 대한 호출이 빠르며 마지막 요소에 액세스 할 때 목록을 반복 할 필요가 없습니다. 아래 예제를 참조하십시오 :

public static int iterRevIterator(List<Integer> list) { 
    int sum = 0; 
    for(ListIterator<Integer> outer = list.listIterator(list.size()); outer.hasPrevious();) { 
     Integer oVal = outer.previous(); 
     for(ListIterator<Integer> inner = list.listIterator(); inner.nextIndex() <= outer.previousIndex();) { 
      sum += oVal * inner.next(); 
     } 
    } 
    return sum; 
} 
관련 문제