문제

Iterator 인터페이스가 확장되지 않음 Iterable?

그만큼 iterator() 메소드는 단순히 반환될 수 있습니다. this.

의도적인 걸까요, 아니면 단지 Java 디자이너의 감독일까요?

다음과 같이 반복자와 함께 for-each 루프를 사용할 수 있으면 편리합니다.

for(Object o : someContainer.listSomeObjects()) {
    ....
}

어디 listSomeObjects() 반복자를 반환합니다.

도움이 되었습니까?

해결책

반복자는 일반적으로 컬렉션에서 단일 인스턴스를 가리키기 때문입니다. 반복적 인 것은 객체에서 반복자를 얻을 수 있음을 의미하며, 요소를 가로 질러 통과 할 수 있으며 단일 인스턴스를 반복 할 필요가 없으며, 이는 반복자가 나타내는 것입니다.

다른 팁

반복자는 상태가 있습니다. 아이디어는 당신이 전화하면 Iterable.iterator() 두 번 얻을 수 있습니다 독립적인 반복자 - 어쨌든 대부분의 반복. 그것은 당신의 시나리오에서는 그렇지 않을 것입니다.

예를 들어, 나는 보통 다음을 쓸 수 있습니다.

public void iterateOver(Iterable<String> strings)
{
    for (String x : strings)
    {
         System.out.println(x);
    }
    for (String x : strings)
    {
         System.out.println(x);
    }
}

그것은 컬렉션을 두 번 인쇄해야하지만, 당신의 계획을 사용하면 두 번째 루프는 항상 즉시 종료됩니다.

$ 0.02의 경우, 반복자가 반복적 인 구현해서는 안된다는 데 전적으로 동의하지만, 루프의 향상된 것도 수락해야한다고 생각합니다. 나는 "반복자를 반복 할 수있는"전체가 언어의 결함에 대한 작업으로 제기된다고 생각합니다.

루프를 위해 강화 된 것의 도입의 모든 이유는 "컬렉션과 배열을 반복 할 때 반복자와 색인 변수의 드루게리와 오류가 발생하기 때문[1].

Collection<Item> items...

for (Iterator<Item> iter = items.iterator(); iter.hasNext(); ) {
    Item item = iter.next();
    ...
}

for (Item item : items) {
    ...
}

그렇다면 왜 동일한 주장이 반복자에 대해 유지되지 않습니까?

Iterator<Iter> iter...
..
while (iter.hasNext()) {
    Item item = iter.next();
    ...
}

for (Item item : iter) {
    ...
}

두 경우 모두 Hasnext () 및 Next ()에 대한 호출이 제거되었으며 내부 루프의 반복자에 대한 언급이 없습니다. 예, 반복적 인 반복기를 만들기 위해 반복성을 재사용 할 수 있지만 모든 것이 For 루프 외부에서 발생한다는 것을 이해합니다. 루프 내부에는 반복자가 반환 한 항목에 대해 한 번에 하나의 항목만으로 진행됩니다.

또한,이를 허용하면 다른 곳에서 지적 된 바와 같이 반복적 인 반복자와 유사한 열거 용 루프를 쉽게 사용할 수 있습니다.

따라서 반복자를 반복적으로 구현하지 말고 For Loop을 업데이트하여 수락하십시오.

건배,

다른 사람들이 지적했듯이 Iterator 그리고 Iterable 두 가지 다른 것입니다.

또한, Iterator 구현은 루프에 대해 향상되었습니다.

또한 정적 메소드 가져 오기에 사용할 때 이와 같은 간단한 어댑터 방법 으로이 제한을 극복하는 것도 사소한 일입니다.

for (String line : in(lines)) {
  System.out.println(line);
}

샘플 구현 :

  /**
   * Adapts an {@link Iterator} to an {@link Iterable} for use in enhanced for
   * loops. If {@link Iterable#iterator()} is invoked more than once, an
   * {@link IllegalStateException} is thrown.
   */
  public static <T> Iterable<T> in(final Iterator<T> iterator) {
    assert iterator != null;
    class SingleUseIterable implements Iterable<T> {
      private boolean used = false;

      @Override
      public Iterator<T> iterator() {
        if (used) {
          throw new IllegalStateException("SingleUseIterable already invoked");
        }
        used = true;
        return iterator;
      }
    }
    return new SingleUseIterable();
  }

Java 8에서 Iterator an Iterable 더 간단해진다 :

for (String s : (Iterable<String>) () -> iterator) {

다른 사람들이 말했듯이 Iterable은 여러 번 호출될 수 있으며 각 호출마다 새로운 Iterator를 반환합니다.Iterator는 한 번만 사용됩니다.따라서 그들은 서로 관련되어 있지만 다른 목적으로 사용됩니다.그러나 실망스럽게도 "compact for" 메소드는 iterable에서만 작동합니다.

아래에서 설명할 내용은 기본 데이터 시퀀스가 ​​일회성인 경우에도 Iterable(더 나은 구문을 위해)을 반환하는 두 세계의 장점을 모두 활용하는 한 가지 방법입니다.

비결은 실제로 작업을 트리거하는 Iterable의 익명 구현을 반환하는 것입니다.따라서 일회성 시퀀스를 생성하는 작업을 수행한 다음 그 위에 Iterator를 반환하는 대신, 액세스할 때마다 작업을 다시 실행하는 Iterable을 반환합니다.낭비처럼 보일 수도 있지만 어쨌든 Iterable을 한 번만 호출하는 경우가 많으며 여러 번 호출하더라도 여전히 합리적인 의미를 갖습니다(Iterator를 Iterable처럼 "보이게" 만드는 간단한 래퍼와는 달리, 이는 두 번 사용해도 실패하지 않습니다).

예를 들어, 데이터베이스의 일련의 개체를 제공하는 DAO가 있고 반복자를 통해 해당 개체에 대한 액세스를 제공하고 싶다고 가정해 보겠습니다.필요하지 않은 경우 메모리에 모든 객체를 생성하는 것을 방지합니다.이제 반복자를 반환할 수 있지만 이로 인해 루프에서 반환된 값을 사용하는 것이 보기 흉해집니다.그래서 대신 모든 것을 Anon Iterable로 래핑합니다.

class MetricDao {
    ...
    /**
     * @return All known metrics.
     */
    public final Iterable<Metric> loadAll() {
        return new Iterable<Metric>() {
            @Override
            public Iterator<Metric> iterator() {
                return sessionFactory.getCurrentSession()
                        .createQuery("from Metric as metric")
                        .iterate();
            }
        };
    }
}

그러면 다음과 같은 코드에서 사용할 수 있습니다.

class DaoUser {
    private MetricDao dao;
    for (Metric existing : dao.loadAll()) {
        // do stuff here...
    }
}

이를 통해 증분 메모리 사용을 유지하면서 컴팩트 for 루프를 사용할 수 있습니다.

이 접근 방식은 "게으른" 접근 방식입니다. Iterable이 요청될 때 작업이 완료되지 않고 나중에 내용이 반복될 때만 작업이 완료되므로 그 결과를 알고 있어야 합니다.DAO를 사용한 예에서는 데이터베이스 트랜잭션 내의 결과를 반복하는 것을 의미합니다.

따라서 다양한 주의 사항이 있지만 이는 여전히 많은 경우에 유용한 관용구가 될 수 있습니다.

놀랍게도, 아무도이 답변을하지 않았습니다. 다음은 "쉽게"반복 할 수있는 방법은 다음과 같습니다. Iterator 새로운 Java 8을 사용하여 Iterator.forEachRemaining() 방법:

Iterator<String> it = ...
it.forEachRemaining(System.out::println);

물론 Foreach 루프와 직접 작동하는 "간단한"솔루션이 있습니다. Iterator 에서 Iterable 람다 :

for (String s : (Iterable<String>) () -> it)
    System.out.println(s);

Iterator 무언가를 반복 할 수있는 인터페이스입니다. 그것은 어떤 종류의 컬렉션을 통해 움직이는 구현입니다.

Iterable 무언가에 액세스 가능한 반복기가 포함되어 있음을 나타내는 기능 인터페이스입니다.

Java8에서 이것은 인생을 매우 쉽게 만듭니다 ... Iterator 그러나 필요합니다 Iterable 당신은 단순히 할 수 있습니다 :

Iterator<T> someIterator;
Iterable<T> = ()->someIterator;

이것은 또한 for-loop에서 작동합니다.

for (T item : ()->someIterator){
    //doSomething with item
}

나는 또한 많은 일을하는 것을 본다 :

public Iterator iterator() {
    return this;
}

그러나 그것은 옳지 않습니다! 이 방법은 당신이 원하는 것이 아닙니다!

방법 iterator() 처음부터 시작하여 새로운 반복자를 반환해야합니다. 따라서 다음과 같은 일을해야합니다.

public class IterableIterator implements Iterator, Iterable {

  //Constructor
  IterableIterator(IterableIterator iter)
  {
    this.initdata = iter.initdata;
  }
  // methods of Iterable

  public Iterator iterator() {
    return new MyClass(this.somedata);
  }

  // methods of Iterator

  public boolean hasNext() {
    // ...
  }

  public Object next() {
    // ...
  }

  public void remove() {
    // ...
  }
}

문제는 :이를 수행하는 추상적 인 수업을 만드는 방법이 있습니까? 따라서 반복적 인 테이터를 얻으려면 다음 두 가지 메소드 만 구현하면됩니다 () 및 hasnext ()

해결 방법을 찾아 여기에 온 경우 사용할 수 있습니다. 반복적 인. (Java 1.6 이상 이용 가능)

예제 사용 (벡터 역전).

import java.util.Vector;
import org.apache.commons.collections4.iterators.IteratorIterable;
import org.apache.commons.collections4.iterators.ReverseListIterator;
public class Test {
    public static void main(String ... args) {
        Vector<String> vs = new Vector<String>();
        vs.add("one");
        vs.add("two");
        for ( String s: vs ) {
            System.out.println(s);
        }
        Iterable<String> is
            = new IteratorIterable(new ReverseListIterator(vs));
        for ( String s: is ) {
            System.out.println(s);
        }
    }
}

인쇄물

one
two
two
one

나는 받아 들여진 답변에 동의하지만 내 자신의 설명을 추가하고 싶습니다.

  • 반복자는 트래버스 상태를 나타냅니다. 예를 들어, 반복자에서 현재 요소를 가져 와서 다음으로 이동할 수 있습니다.

  • 반복성은 가로 질 수있는 컬렉션을 나타냅니다. 원하는만큼의 반복기를 반환 할 수 있으며, 각각 자체 트래버스 상태를 나타냅니다. 하나의 반복기는 첫 번째 요소를 가리키고 있고 다른 반복은 3 번째 요소를 가리킬 수 있습니다.

루프를위한 Java가 반복자와 반복적 인 것을 모두 받아들이면 좋을 것입니다.

단순성을 위해 반복자와 반복 가능한 두 가지 개념이며, 반복 가능한 것은 단순히 "반복자를 반환 할 수있다"는 속기입니다. 나는 당신의 코드가 다음과 같아야한다고 생각합니다.

for(Object o : someContainer) {
}

SOMECONGAINER 인스턴스와 함께 SomeContainer extends Iterable<Object>

따로 : Scala는 반복자에 Toiterable () 메소드가 있습니다. 보다 스칼라는 반복자에서 반복성으로 암시 적 또는 명시 적 변환

관련 메모에서 Apache Commons Collections의 반복적 인 어댑터가 유용하다는 것을 알 수 있습니다. 반복자에서 인스턴스를 작성하면 해당 반복 가능이 있습니다.

https://commons.apache.org/proper/commons-collections/apidocs/org/apache/commons/collession4/iterators/iteratoriteritorable.html

ID : org.apache.commons : Commons-Collections4 : 4.0

반복자는 상태를 저장하며 "다음" 요소를 가지며 반복되면 "소진"됩니다.문제가 어디에 있는지 확인하려면 다음 코드를 실행하세요. 몇 개의 숫자가 인쇄됩니까?

Iterator<Integer> iterator = Arrays.asList(1,2,3).iterator();
Iterable<Integer> myIterable = ()->iterator;
for(Integer i : myIterable) System.out.print(i);
System.out.println();
for(Integer i : myIterable) System.out.print(i);

다음 예제를 시도 할 수 있습니다.

List ispresent=new ArrayList();
Iterator iterator=ispresent.iterator();
while(iterator.hasNext())
{
    System.out.println(iterator.next());
}
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top