Java에서 Iterable 크기 가져 오기


90

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

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

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

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

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


왜? 둘 다 O (N)이기 때문에 둘 다 정말 나쁜 생각입니다. 컬렉션을 두 번 반복하지 않도록해야합니다.
론의 후작

3
두 번째는 작동하지 않아야합니다. 사전에 전화 remove()하지 않고는 전화를 걸 수 없습니다 next().
Louis Wasserman 2012

답변:


124

요약 : 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)구아바 당신을 위해 않습니다.


그는 요소에 관심이 없으며 제거해도 상관 없다고 말합니다.
aioobe

작은 설명 : 그것은 요소를 제거 에서values
미켈

1
그러나 코드의 다른 부분은 여전히 ​​동일한 Iterable을 사용할 수 있습니다. 그리고 지금이 아니라면 아마도 미래에.
필립 웬 들러

Google Guava 답변을 더 눈에 띄게 만드는 것이 좋습니다. 사소한 일이지만 사람들이이 코드를 다시 작성하게 할 이유가 없습니다.
Stephen Harrison

8
자바 8을 사용하는 경우, 스트림을 생성하고 그 안에 요소 수 : Stream.of (myIterable) .count ()
FrankBr

41

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;
    }

1
누군가,이 사람에게 메달을 건네주세요.
Pramesh Bajracharya

Sort 에서는 작동하지 않습니다 . New Bee의 답변이 저에게 효과적입니다.
Sabir Khan

18

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

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

2
이것은 나에게 직관적 인 접근 방식이며 감사 할 수 있습니다. 몇 분 전에 사용했습니다. 감사.
Matt Cremeens 2015 년

2
네, 그것은 직관적이지만, 슬프게도 당신은 값 ... 사용되지 않은 경보 억제해야
닐스 - 오 - 매트

이 솔루션 덕분에 실제로 객체의 크기를 반환합니다. 유일한 단점은 나중에 동일한 객체를 통해 다시 반복하려면 먼저 어떻게 든 재설정해야한다는 것입니다.
Zsolti

6

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

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

    new Iterable(){

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

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

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

6

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

Lists.newArrayList(iterable).size();

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

import com.google.common.collect.Lists;

3
리스트는 구아바 클래스입니다
폴 잭슨

2

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

E next()

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

void remove()

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


이 답변은 기술적으로 정확하지만 오해의 소지가 있습니다. 호출 remove은의 요소를 계산하는 잘못된 방법으로 이미 언급 Iterator되었으므로 우리가하지 않을 일이 구현되었는지 여부는 실제로 중요하지 않습니다.
Stephen Harrison

1
정확히 어떤 부분이 오해의 소지가 있습니까? 그리고 상황에서도 remove 되고 구현, 왜 그것을 사용하는 것이 잘못된 것입니까? Btw, downvotes는 일반적으로 잘못된 답변이나 나쁜 조언을 제공하는 답변에 사용됩니다. 이 답변이 어떤 것에 대해 어떻게 자격이 있는지 볼 수 없습니다.
aioobe

2

자바 8 이상

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

0

저에 관해서는 이것들은 단지 다른 방법입니다. 첫 번째는 반복중인 객체를 변경하지 않고 그대로두고 초는 비워 둡니다. 문제는 무엇을하고 싶은지입니다. 제거의 복잡성은 반복 가능한 객체의 구현을 기반으로합니다. 컬렉션을 사용하는 경우-Kazekage Gaara가 제안한 것과 같은 크기를 얻으십시오-일반적으로 최상의 접근 성능 현명한 방법입니다.


-2

요소 수를 얻기 위해 단순히 size()방법을 사용하지 않는 이유는 무엇 Collection입니까?

Iterator 반복 할뿐입니다.


4
누가 컬렉션을 사용하고 있다고하나요? :-)
aioobe

요소 제거를 지원하는 반복기를 사용하고 있습니다. 반복자 루프에 들어가기 전에 크기를 선택하는 경우 제거에주의하고 그에 따라 값을 업데이트해야합니다.
Miquel

1
크기를 확인할 컬렉션이없는 이유의 예 : Iterable 만 반환하는 타사 API 메서드를 호출 할 수 있습니다.
SteveT 2011

2
이 답변은 혼란 IteratorIterable. 올바른 방법은 투표 된 답변을 참조하십시오.
Stephen Harrison

-4

루프를 사용하고 각 요소를 계산하거나 타사 라이브러리를 사용하는 대신 ArrayList에서 iterable을 타입 캐스트하고 크기를 가져올 수 있습니다.

((ArrayList) iterable).size();

3
모든 반복 가능 객체는 그래도 ArrayList에 캐스팅 될 수있다
알렉산더 밀스
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.