2017-04-24 1 views
1

List 인터페이스를 사용하여 순환 연결 목록 구현을 만들려고하고 흥미로운 부작용을 발견했습니다.순환 링크 목록 및 반복기 API의 확실성 부족

CircularLinkedList이 List 계약을 충족 시키더라도 다른 현재 구현 된 collection 클래스는 깨집니다!

공공 부울 hasNext()리스트가있는 경우

true를 반환 다음 반복자 인터페이스는 hasNext()와 hasPrevious에 대해 다음 계약() 메소드를 제공합니다 -

문제는 이것이다 이 순방향으로 목록을 이동할 때 반복기는 더 많은 요소를 갖습니다. (다음 예외를 throw하는 일없이 요소를 돌려주는 경우 즉, true를 반환합니다.)

공공 부울 hasPrevious()

반환 사실이리스트 반복자가 한층 더 요소를 가지고있는 경우 목록을 통과 할 때 반대 방향으로. (이전의 예외를 throw하는 일없이 요소를 돌려주는 경우 즉, true를 반환합니다.)

이제 원형 목록에서 이들 각각은해야 계약 리턴 거짓 경우에만 목록이있는 경우로 비었다. 이 각각의 요소를 추가로 반복을 제한하는 방법이 사용 hasNext() - 당신이 오퍼레이션과 addAll() 방법을 사용하여 다른 컬렉션에 적절한리스트 반복자와 원형 목록을 추가 할 때

문제는 그 자체를 보여줍니다 . 따라서 루프가 종료되지 않습니다!

현재 hasNext() 메서드를보고 있거나 hasNext가 반환되도록 재정의 된 하위 클래스를 만드는 경우 목록을 연결된 목록처럼 보이게하려면 ListIterator 계약을 위반하는 것이 좋습니다. iterator() 메소드에 의해.

두 질문 :

  1. 반복자 또는 반복자 계약을 깨지 않고이 일을 더 나은 방법이 있나요?

  2. 누구든지 이것이 (상속 된 동작의 출처 인) AbstractCollection 클래스의 결함이라고 생각하는 사람이 있습니까? 일부 콜렉션은 추가 할 콜렉션의 toArray() 메소드를 호출하고 배열의 각 요소를 추가하여 더 강력한 방법으로 추가 작업을 수행합니다. 제 생각에는

답변

1

이는 어느 쪽도 컬렉션 API에 나 방식에 결함이 두 방법 hasNexthasPrevious에 대한 계약은 정의되지 않습니다.

문제는 당신이 당신의 원형 목록에 대해 생각하는 방식에서 하네 :

  • 목록 요소의 고정 된 크기 때문에 반복자 시작과가있는 방식으로 주문 할 수 있어야있다 종료.
  • hasNexthasPrevious에 응답하기 위해 목록에서 요소를 구성한 방법은 중요하지 않습니다. 순서 지정은 리턴되는 요소 만 정의합니다.

반복자가 동일한 요소 (목록의 절대 위치와 관련된 ID)를 반환하면 반복기 구현이 잘못되었습니다.

목록에 포함 된 요소의 수에서 요소를 정렬하는 방법에 대한 아이디어를 분리해야합니다. 목록의 요소 수는 size의 결과로 정의됩니다. 따라서 앞으로 만 이동하는 경우 hasNext은 번으로 응답해야합니다. hasNext에서 false을 대답 한 후 역방향으로 탐색 할 경우 hasPrevious에 대해서도 마찬가지입니다.