2011-12-18 2 views
3

가능한 중복 :확장 for 루프가 반복자에서 작동하지 않는 이유는 무엇입니까?

List<X> list = ... 
for(X x : list) { ... } 

내가해야 할 것은 :

Iterator<X> listIterator = ... 
for(X x : listIterator){ ... } 

Why is Java's Iterator not an Iterable?

우리 모두 자바의 알은 for 루프를 확장

자바에서는 이것을 허용하지 않습니다. 사양이이 부분을 지원하지 않는 데는 이유가 있는지 궁금합니다..

내가 파일 형식의 종류에 대한 독자를 쓰고 있어요 :

여기 내 유스 케이스입니다. 이러한 파일에는 읽을 항목이 들어 있습니다. 이 예제에서는 BufferedReader를 다시 작성하려고하고 String 요소를 사용한다고 가정합니다. 차라리 뭔가 좋은 같은 물론

for(String line : reader){ 
    ... 
} 

이있을 것이다

for(String line = reader.readLine(); line != null; line = reader.readLine(){ 
    ... 
} 

: 같은

내가 못생긴 코드를 작성하는 저를 강제로 원래 BufferedReader의 API 스타일로 아주 불행 해요 내 BufferedReaderIterable<String>을 구현할 수 있습니다. 그러나 이는 여러 번 호출 될 수있는 iterator() 메서드가 있음을 의미합니다. 파일에서 찾을 수 없으므로 필자는 다중 병렬 반복기를 실제로 지원할 수 없습니다.

BufferedReader을 구현하면 Iterable<String> 대신 Iterator<String>을 구현하는 것이 훨씬 합리적입니다. 하지만 난. 당신은 파일을 더 다음 번에 열 수있는 여러 병렬 반복자를 지원할 수 물론

+0

고급 루프가 "반복기"방법을 여러 번 호출하는지 확인 했습니까? 나는 그것이 단지 한 번만한다고 가정 할 것이다. –

+1

제목 질문에 대한 대답은 "그것이 언어가 정의 된 방식이기 때문에"이다. –

+2

다시 말하지만, 나는 그것이 복제본이라는 것에 동의하지 않습니다. 나는 두 인터페이스의 차이점을 잘 알고 있습니다. 이 차이가 for 루프와 관련하여 왜 중요한지 묻습니다. 나는 또한 그것의 지정이 이런 식으로 알고있다. 나는 그것이 왜 이렇게 지정되었는지 궁금합니다. – Stefan

답변

1

foreach 루프에 대한 계약이기 때문에 모든 요소를 반복합니다. 그것은 단지 Iterator 당신이 그것을 반 소비 Iterator과는 차이를 모르겠다.

Set<String> set = new HashSet(Arrays.asList(new String [] {"One", "Two", "Three"})); 
Iterator i = set.iterator(); 
// Consume the first. 
String first = i.next(); 
for (String s : i) { // Error here. 

} 
을 줄 수을 허용 한 경우 0

나는 물건을 더 쉽게 만들 것이라는 점을 인정하지만 컬렉션에 의 모든 항목을 다뤘다는 사실을 알지 못하기 때문에 심각한 버그가 발생할 수도 있습니다.

// Works fine because Set is Iterable and the contract is satisfied 
// that this will iterate over <b>all</b> of the entries. 
for (String s : set) { 
} 

과도 숫자 Iterable을 만들면 언제든지 해킹 할 수 있습니다. 지금은 테스트 할 수 없지만 다음과 같은 내용이 있습니다.

for (String s : new Iterable { 
    public iterator<String>() { 
    return set.iterator(); 
    } 
}) { 
} 

번거로우 시지만 작동해야합니다.

+0

정적 메서드로 해킹을보다 명확하게 구현할 수 있습니다. [관련 질문] (http://stackoverflow.com/a/8555153/304)에 하나 추가했습니다. – McDowell

+0

좋은 점 Paul. 구문 론적으로 우아하면서 foreach의 의미는 파일의 중간에서 시작할 때 변경됩니다. 검색 할 수없는 스트림에서 읽기는 foreach 의미를 따라갈 수 없으므로 해결 방법을 사용하더라도 잘못 사용하게됩니다. – Stefan

+0

@McDowell - 고마워 ... 지금 자바 5가 없으므로 기계를 사용하고 있으므로 테스트 할 수 없습니다. 그건 당신이 한 번만 '반복자'로 만든 방법에 영리합니다. @Lawnmower - foreach 루프를 악용하는 것이 잘못되었다는 것을 강조하는 것이 중요합니다. 특히 'this'를 반환하여 '반복자'를 반복 가능하게 만드는 것이 중요합니다. 그것은 위험으로 가득차 있습니다. 알림 주셔서 감사. – OldCurmudgeon

1

:-(for 문을 사용할 수 없습니다.

class BufferedReader() implements Iterable<String> { 
    String fileName; 
    InputStreamReader in; 

    public BufferedReader(String fileName) { 
     this.fileName = fileName; 
     in = new InputStreamReader(new FileInputStream(fileName)); 
    } 
    public Iterator<String> iterator() { 
     return new Iterator<String>() { 
      BufferedReader in = new BufferedReader(fileName); 
      String nextLine = in.readLine(); 
      public boolean hasNext() { 
       return nextLine != null; 
      } 
      public String next() { 
       String str = nextLine; 
       nextLine = in.readLine(); 
       return str; 
      } 
     } 
    } 
} 
+0

당신은'IOException'을 처리하지 않습니다 – McDowell

+0

그건 좋은 생각입니다. 나는 파일을 실제로 읽지 않는다고 지정 했어야했다. 나는 InputStream 만 가지고 시작한다. 이것은 예를 들어 네트워크 소켓에서 직접 읽는 경우입니다. – Stefan

+0

또한 모든 데이터를 ArrayList로 읽은 다음 BufferedReader에서 해당 목록을 읽을 수 있습니다. 그럼 당신은 찾을 수 있습니다. 또는 어쨌든 Iterable을 구현하십시오. for 루프는 iterator 메소드를 한 번만 호출합니다. 그래서 문제가 없어야합니다. – SpiderPig

관련 문제