Get size of an Iterable in Java

JavaIterable

Java Problem Overview


I need to figure out the number of elements in an Iterable in Java. I know I can do this:

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

I could also do something like this, because I do not need the objects in the Iterable any further:

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

A small scale benchmark did not show much performance difference, any comments or other ideas for this problem?

Java Solutions


Solution 1 - Java

TL;DR: Use the utility method Iterables.size(Iterable) of the great Guava library.

Of your two code snippets, you should use the first one, because the second one will remove all elements from values, so it is empty afterwards. Changing a data structure for a simple query like its size is very unexpected.

For performance, this depends on your data structure. If it is for example in fact an ArrayList, removing elements from the beginning (what your second method is doing) is very slow (calculating the size becomes O(n*n) instead of O(n) as it should be).

In general, if there is the chance that values is actually a Collection and not only an Iterable, check this and call size() in case:

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

The call to size() will usually be much faster than counting the number of elements, and this trick is exactly what Iterables.size(Iterable) of Guava does for you.

Solution 2 - Java

If you are working with java 8 you may use:

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

it will only work if the iterable source has a determined size. Most Spliterators for Collections will, but you may have issues if it comes from a HashSetor ResultSetfor instance.

You can check the javadoc here.

If Java 8 is not an option, or if you don't know where the iterable comes from, you can use the same approach as 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;
    }

Solution 3 - Java

This is perhaps a bit late, but may help someone. I come across similar issue with Iterable in my codebase and solution was to use for each without explicitly calling values.iterator();.

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

Solution 4 - Java

You can cast your iterable to a list then use .size() on it.

Lists.newArrayList(iterable).size();

For the sake of clarity, the above method will require the following import:

import com.google.common.collect.Lists;

Solution 5 - Java

Strictly speaking, Iterable does not have size. Think data structure like a cycle.

And think about following Iterable instance, No size:

	new Iterable(){

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

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

Solution 6 - Java

java 8 and above

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

Solution 7 - Java

I would go for it.next() for the simple reason that next() is guaranteed to be implemented, while remove() is an optional operation.

> E next() > > Returns the next element in the iteration. > > void remove() > > Removes from the underlying collection the last element returned by the iterator (optional operation).

Solution 8 - Java

As for me, these are just different methods. The first one leaves the object you're iterating on unchanged, while the seconds leaves it empty. The question is what do you want to do. The complexity of removing is based on implementation of your iterable object. If you're using Collections - just obtain the size like was proposed by Kazekage Gaara - its usually the best approach performance wise.

Solution 9 - Java

Why don't you simply use the size() method on your Collection to get the number of elements?

Iterator is just meant to iterate,nothing else.

Solution 10 - Java

Instead of using loops and counting each element or using and third party library we can simply typecast the iterable in ArrayList and get its size.

((ArrayList) iterable).size();

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionjs84View Question on Stackoverflow
Solution 1 - JavaPhilipp WendlerView Answer on Stackoverflow
Solution 2 - JavaArnaudRView Answer on Stackoverflow
Solution 3 - JavapilotView Answer on Stackoverflow
Solution 4 - JavastratagemView Answer on Stackoverflow
Solution 5 - Java卢声远 Shengyuan LuView Answer on Stackoverflow
Solution 6 - JavaNew BeeView Answer on Stackoverflow
Solution 7 - JavaaioobeView Answer on Stackoverflow
Solution 8 - JavaMark BramnikView Answer on Stackoverflow
Solution 9 - JavaKazekage GaaraView Answer on Stackoverflow
Solution 10 - JavafatimasajjadView Answer on Stackoverflow