IT story

반복기의 개수 / 길이 / 크기를 얻는 가장 좋은 방법은 무엇입니까?

hot-time 2020. 9. 11. 19:38
반응형

반복기의 개수 / 길이 / 크기를 얻는 가장 좋은 방법은 무엇입니까?


반복기의 수를 얻는 "계산적으로"빠른 방법이 있습니까?

int i = 0;
for ( ; some_iterator.hasNext() ; ++i ) some_iterator.next();

... CPU 사이클 낭비처럼 보입니다.


반복자를 가지고 있다면 그것은 당신이해야 할 일입니다. 그것은 얼마나 많은 항목을 반복 해야할지 모르기 때문에 그 결과를 쿼리 할 수 ​​없습니다. 이를 수행하는 것처럼 보이는 유틸리티 메서드 (예 : Iterators.size()Guava)가 있지만 그 아래에서는 거의 동일한 작업을 수행하고 있습니다.

그러나 많은 이터레이터는 컬렉션에서 가져 오므로 종종 크기를 쿼리 할 수 ​​있습니다. 그리고 그것이 반복자를 얻고있는 사용자가 만든 클래스 인 경우 해당 클래스에 size () 메서드를 제공 할 수 있습니다.

간단히 말해서, 반복자 있는 상황에서 더 좋은 방법은 없지만 크기를 직접 가져올 수있는 기본 컬렉션이나 객체에 액세스 할 수있는 경우가 훨씬 더 많습니다.


Guava 라이브러리 사용 :

int size = Iterators.size(iterator);

내부적으로는 모든 요소를 ​​반복하므로 편의를 위해.


반복자의 끝에 도달하면 코드에서 예외가 발생합니다. 다음과 같이 할 수 있습니다.

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();

당신이 가진 모든 것이 반복자라면, "더 나은"방법은 없습니다. 이터레이터가 컬렉션에서 나온다면 크기만큼 할 수 있습니다.

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

사용 구아바 라이브러리를 , 또 다른 옵션은 변환하는 IterableA를 List.

List list = Lists.newArrayList(some_iterator);
int count = list.size();

크기를 가져온 후 반복기의 요소에 액세스해야하는 경우에도이를 사용하십시오. 사용 Iterators.size()하면 더 이상 반복 된 요소에 액세스 할 수 없습니다.


There is no more efficient way, if all you have is the iterator. And if the iterator can only be used once, then getting the count before you get the iterator's contents is ... problematic.

The solution is either to change your application so that it doesn't need the count, or to obtain the count by some other means. (For example, pass a Collection rather than Iterator ...)


iterator object contains the same number of elements what your collection contained.

List<E> a =...;
Iterator<E> i = a.iterator();
int size = a.size();//Because iterators size is equal to list a's size.

But instead of getting the size of iterator and iterating through index 0 to that size, it is better to iterate through the method next() of the iterator.

참고URL : https://stackoverflow.com/questions/9720195/what-is-the-best-way-to-get-the-count-length-size-of-an-iterator

반응형