반복기의 수를 얻는 “계산적으로”빠른 방법이 있습니까?
int i = 0;
for ( ; some_iterator.hasNext() ; ++i ) some_iterator.next();
… CPU 사이클 낭비처럼 보입니다.
답변
반복자를 가지고 있다면 그게해야 할 일입니다. 반복 할 항목이 몇 개 남았는지 알지 못하기 때문에 해당 결과를 쿼리 할 수 없습니다. 이를 수행하는 것처럼 보이는 유틸리티 메서드 (예 : Iterators.size()
Guava)가 있지만 그 아래에서는 거의 동일한 작업을 수행하고 있습니다.
그러나 많은 이터레이터는 컬렉션에서 가져 오므로 종종 크기를 쿼리 할 수 있습니다. 그리고 그것이 반복자를 얻고있는 사용자가 만든 클래스 인 경우 해당 클래스에 size () 메서드를 제공 할 수 있습니다.
간단히 말해서, 반복자 만 있는 상황에서 더 좋은 방법은 없지만 크기를 직접 가져올 수있는 기본 컬렉션이나 개체에 액세스 할 수있는 경우가 훨씬 더 많습니다.
답변
답변
반복자의 끝에 도달하면 코드에서 예외가 발생합니다. 다음과 같이 할 수 있습니다.
int i = 0;
while(iterator.hasNext()) {
i++;
iterator.next();
}
기본 컬렉션에 대한 액세스 권한이있는 경우 다음을 호출 할 수 있습니다 coll.size()
.
수정
확인 수정했습니다 …
답변
항상 반복해야합니다. 그러나 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");
}
};
답변
반복자 만 있으면 더 효율적인 방법은 없습니다. 그리고 반복기를 한 번만 사용할 수 있다면 반복자의 내용을 얻기 전에 개수를 얻는 것이 문제가됩니다.
해결책은 카운트가 필요하지 않도록 애플리케이션을 변경하거나 다른 방법으로 카운트를 얻는 것입니다. (예를 들어 … Collection
보다는 a를 전달하십시오 Iterator
.)