[java] Java에서 Iterable 크기 가져 오기

IterableJava 의 요소 수를 알아야합니다 . 나는 이것을 할 수 있다는 것을 안다.

Iterable values = ...
it = values.iterator();
while (it.hasNext()) {
  it.next();
  sum++;
}

Iterable의 객체가 더 이상 필요하지 않기 때문에 이와 같은 작업을 수행 할 수도 있습니다.

it = values.iterator();
while (it.hasNext()) {
  it.remove();
  sum++;
}

소규모 벤치 마크에서는이 문제에 대한 성능 차이, 의견 또는 기타 아이디어가 많지 않았습니까?



답변

요약 : Iterables.size(Iterable)위대한 Guava 라이브러리 의 유틸리티 방법 을 사용하십시오 .

두 코드 스 니펫 중 첫 번째 코드 스 니펫을 사용해야합니다. 두 번째 코드는 모든 요소를 values 하므로 나중에 비어 있습니다. 크기와 같은 간단한 쿼리의 데이터 구조를 변경하는 것은 예상치 못한 일입니다.

성능을 위해 이것은 데이터 구조에 따라 다릅니다. 예를 들어 실제로 ArrayList이면 처음부터 요소를 제거하는 것이 (두 번째 방법이 수행하는 작업) 매우 느립니다 (크기를 계산하는 것은 O (n) 대신 O (n * n)이됩니다).

일반적으로 일뿐 만 아니라 values실제로 a 일 가능성 이 있는 경우 이를 확인하고 다음과 같은 경우에 호출하십시오 .CollectionIterablesize()

if (values instanceof Collection<?>) {
  return ((Collection<?>)values).size();
}
// use Iterator here...

에 대한 호출 size()의 뜻은 일반적으로 훨씬 빠르게 요소의 수를 계산보다,이 트릭은 정확히 무엇인가 Iterables.size(Iterable)구아바 당신을 위해 않습니다.


답변

Java 8로 작업하는 경우 다음을 사용할 수 있습니다.

Iterable values = ...
long size = values.spliterator().getExactSizeIfKnown();

반복 가능한 소스의 크기가 결정된 경우에만 작동합니다. 그것에서 오는 경우 컬렉션에 대한 대부분의 Spliterators,하지만 당신은 문제가있을 수 있습니다 것 HashSet또는 ResultSet예를 들면.

여기 에서 javadoc을 확인할 수 있습니다 .

Java 8이 옵션이 아니 거나 iterable의 출처를 모르는 경우 guava와 동일한 접근 방식을 사용할 수 있습니다.

  if (iterable instanceof Collection) {
        return ((Collection<?>) iterable).size();
    } else {
        int count = 0;
        Iterator iterator = iterable.iterator();
        while(iterator.hasNext()) {
            iterator.next();
            count++;
        }
        return count;
    }


답변

이것은 아마도 조금 늦었지만 누군가를 도울 수 있습니다. Iterable내 코드베이스에서 비슷한 문제가 발생 했으며 솔루션은 for each명시 적으로 호출하지 않고 사용하는 것이 었습니다 values.iterator();.

int size = 0;
for(T value : values) {
   size++;
}


답변

엄밀히 말하면 Iterable에는 크기가 없습니다. 데이터 구조를 순환이라고 생각하십시오.

그리고 Iterable 인스턴스, 크기 없음을 고려하십시오.

    new Iterable(){

        @Override public Iterator iterator() {
            return new Iterator(){

                @Override
                public boolean hasNext() {
                    return isExternalSystemAvailble();
                }

                @Override
                public Object next() {
                    return fetchDataFromExternalSystem();
                }};
        }};


답변

iterable을 목록으로 캐스트 한 다음 .size ()를 사용할 수 있습니다.

Lists.newArrayList(iterable).size();

명확성을 위해 위의 방법에는 다음 가져 오기가 필요합니다.

import com.google.common.collect.Lists;


답변

나는 구현이 보장 it.next()되는 간단한 이유 를 위해 갈 것입니다 .next()remove()

E next()

반복에서 다음 요소를 반환합니다.

void remove()

반복기에 의해 반환 된 마지막 요소를 내부 컬렉션에서 제거합니다 (선택적 작업) .


답변

자바 8 이상

StreamSupport.stream(data.spliterator(), false).count();