0

I have this code:

int size = Iterables.size(components);
log.info("Number of components found (before convert): " +  size);

List<Component> listOfComponents = Lists.newArrayList(components);
size = listOfComponents.size();
log.info("Number of components found (after convert): " +  size);

for (Component component : listOfComponents) {
  log.info("component :  " + component);
}

Where Component is: org.sonatype.nexus.repository.storage.Component

When I run it it prints:

Number of components found (before convert): 2
Number of components found (after convert): 0

So after I convert my iterable to a list the elements are no longer there. Also I never get into the following loop.

why does the elements not get copied to the list, thats what the docs say:

Creates a mutable ArrayList instance containing the given elements; a very thin shortcut for creating an empty list then calling Iterables.addAll.

u123
  • 15,603
  • 58
  • 186
  • 303

2 Answers2

4

You need to understand that an Iterable returned by Guava's Iterables is a once-only iterable. It turns out your Iterable is a once-only iterable.1 After you iterate it once, it doesn't throw upon subsequent iteration but instead is empty.

Hence, your calling Iterables.size on it effectively empties the Iterable, and that's why the resulting ArrayList is empty.

Instead, you should dump your Iterable to an ArrayList as soon as possible.


1 Sentence deleted because it turns out that Guava adheres to the de-facto standard of Iterables being iterable multiple times.

Tomasz Linkowski
  • 4,386
  • 23
  • 38
  • awesome answer ! – Luca Tampellini Aug 02 '18 at 09:49
  • 3
    I agree that `components` is a once-only iterable, but Guava does not provide any once-only iterables. The once-only iterable is coming from somewhere else. (At most, Guava might be wrapping an existing once-only iterable, resulting in another once-only iterable.) – Chris Povirk Aug 02 '18 at 13:18
  • 1
    Yeah, as @ChrisPovirk says, once-only iterables are something that Guava _explicitly_ avoids providing, despite numerous requests for, say, a method that creates an `Iterable` view of an `Iterator` (which would be once-only). – ColinD Aug 02 '18 at 14:53
  • @ChrisPovirk @ColinD: I apologize for posting this false claim about `Iterables`. I should have checked this before posting. You might wonder how I knew it's an `Iterable` from Guava - I knew it from [this Q&A](https://stackoverflow.com/a/51641345/2032415). So indeed, as @ChrisPovirk suggested, it must have been the case that Guava wrapped an existing once-only `Iterable`. Anyway, I take the downvote as well-deserved ;) – Tomasz Linkowski Aug 02 '18 at 17:09
0

When you call Iterables.size(components) it uses the Iterable you pass and iterates through the collection (calling hasNext and next on the Iterator from the passed Iterable) to find out the size.

So, when you make the second call to newArrayList, the Itertor is empty now (calling hasNext will return false).

You need to create a new Iterable and pass to newArrayList

Thiyagu
  • 17,362
  • 5
  • 42
  • 79