반복기의 수를 얻는 "계산적으로"빠른 방법이 있습니까?
int i = 0;
for ( ; some_iterator.hasNext() ; ++i ) some_iterator.next();
... CPU 사이클 낭비처럼 보입니다.
반복기의 수를 얻는 "계산적으로"빠른 방법이 있습니까?
int i = 0;
for ( ; some_iterator.hasNext() ; ++i ) some_iterator.next();
... CPU 사이클 낭비처럼 보입니다.
to provide an implementation-independent method for access, in which the user does not need to know whether the underlying implementation is some form of array or of linked list, and allows the user go through the collection without explicit indexing.
penguin.ewu.edu/~trolfe/LinkedSort/Iterator.html
답변:
반복자를 가지고 있다면 그게해야 할 일입니다. 반복 할 항목이 몇 개 남았는지 알지 못하기 때문에 해당 결과를 쿼리 할 수 없습니다. 이를 수행하는 것처럼 보이는 유틸리티 메서드 (예 : Iterators.size()
Guava)가 있지만 그 아래에서는 거의 동일한 작업을 수행하고 있습니다.
그러나 많은 이터레이터는 컬렉션에서 가져 오므로 종종 크기를 쿼리 할 수 있습니다. 그리고 그것이 반복자를 얻고있는 사용자가 만든 클래스 인 경우 해당 클래스에 size () 메서드를 제공 할 수 있습니다.
간단히 말해서, 반복자 만 있는 상황에서 더 좋은 방법은 없지만 크기를 직접 가져올 수있는 기본 컬렉션이나 개체에 액세스 할 수있는 경우가 훨씬 더 많습니다.
Iterators.size(...)
(아래의 다른 주석과 java-doc에 언급 된) 의 부작용에주의하십시오 . "반복자에 남아있는 요소의 수를 반환합니다. 반복자는 고갈 된 상태로 남습니다. hasNext () 메서드는 false를 반환합니다." 즉, 나중에 더 이상 Iterator를 사용할 수 없습니다. Lists.newArrayList(some_iterator);
도움이 될 수 있습니다.
항상 반복해야합니다. 그러나 Java 8, 9를 사용하여 명시 적으로 반복하지 않고도 계산을 수행 할 수 있습니다.
Iterable<Integer> newIterable = () -> iter;
long count = StreamSupport.stream(newIterable.spliterator(), false).count();
다음은 테스트입니다.
public static void main(String[] args) throws IOException {
Iterator<Integer> iter = Arrays.asList(1, 2, 3, 4, 5).iterator();
Iterable<Integer> newIterable = () -> iter;
long count = StreamSupport.stream(newIterable.spliterator(), false).count();
System.out.println(count);
}
이것은 다음을 인쇄합니다.
5
흥미롭게 parallel
도이 호출 에서 플래그를 변경하여 여기서 카운트 작업을 병렬화 할 수 있습니다 .
long count = StreamSupport.stream(newIterable.spliterator(), *true*).count();
사용 구아바 라이브러리를 , 또 다른 옵션은 변환하는 Iterable
A를 List
.
List list = Lists.newArrayList(some_iterator);
int count = list.size();
크기를 가져온 후 반복기의 요소에 액세스해야하는 경우에도이를 사용하십시오. 사용 Iterators.size()
하면 더 이상 반복 된 요소에 액세스 할 수 없습니다.
당신이 가진 모든 것이 반복자라면, "더 나은"방법은 없습니다. 이터레이터가 컬렉션에서 나온다면 크기만큼 할 수 있습니다.
Iterator는 고유 한 값을 탐색하기위한 인터페이스 일 뿐이므로 다음과 같은 코드를 사용하는 것이 좋습니다.
new Iterator<Long>() {
final Random r = new Random();
@Override
public boolean hasNext() {
return true;
}
@Override
public Long next() {
return r.nextLong();
}
@Override
public void remove() {
throw new IllegalArgumentException("Not implemented");
}
};
또는
new Iterator<BigInteger>() {
BigInteger next = BigInteger.ZERO;
@Override
public boolean hasNext() {
return true;
}
@Override
public BigInteger next() {
BigInteger current = next;
next = next.add(BigInteger.ONE);
return current;
}
@Override
public void remove() {
throw new IllegalArgumentException("Not implemented");
}
};