More efficient way to use "Expression" in enhanced "for" cycles

Asked

Viewed 104 times

0

Among the following forms, which the most efficient?

...
//assumindo que o método pegaListaPessoas() pesquisa na base de dados todos as pessoas
for (Pessoa pAux : pegaListaPessoas())
{
    //executo alguma coisa
}

or:

...
//assumindo que o método pegaListaPessoas() pesquisa na base de dados todos as pessoas
List<Pessoa> pessoas = pegaListaPessoas();
for (Pessoa pAux : pessoas)
{
    //executo alguma coisa
}

1 answer

5


Always the best way for you to figure this out is to measure. What may seem one thing in theory can be shown another in a specific real case. In fact this can be considered premature optimization.

If you ask random people on the internet who don’t know an implementation, the exact conditions of your application and the performance requirements, don’t expect something very precise.

I cannot answer with absolute certainty because I do not know the implementation of pegaListaPessoas(), I don’t know the implementation of what it returns until because I don’t even know what it returns. But it could kick with good chance of hitting that makes no difference.

What does this method return? A Iterable that scans a cached list of database content? And the implementation of this interface is a List? Or is it a proper implementation where the next() will consult the database? If there is a performance problem, it may be in a different place than imagined.

Roughly the implementations must be compiled to the equivalent of

for (Iterator<Pessoa> i = pegaListaPessoas().iterator(); i.hasNext(); i.next()) {

and

List<Pessoa> pessoas = pegaListaPessoas();
for (Iterator<Pessoa> i = pessoas.iterator(); i.hasNext(); i.next()) {

In the first case, he calls the pegaListaPessoas() the first time, gets a iterator of the list created by the method, all this before the first ; and with each step it will catch the next item of iteration with the next() (after the second ;) and check if there are any other items with the hasNext(). Only the last two are executed at each step. Initialization is performed only once.

The only difference in the second case is that the list is generated before starting the loop.

In fact if you visualize it as a while becomes more obvious:

Iterator<Pessoa> i = pegaListaPessoas().iterator();
while (i.hasNext()){
     Pessoa p = i.next();
}

and

List<Pessoa> pessoas = pegaListaPessoas();
Iterator<Pessoa> i = pessoas.iterator();
while(i.hasNext()){
     Pessoa p = i.next();
}

I put in the Github for future reference.

You understand that the secret is iterator? And as far as I know one loop for in can only run on top of collections implementing the interface Iterable (perhaps with the exception of a array, String and other types that the language is aware of and use the index directly).

  • Thank you @bigown for the prompt response to my question. I have carefully read your reply and understand your point. But I thought that some questions, although correct are not part of what is the scope of my question, I think it would be something much simpler.

  • @Coldhack So make the question clearer.

  • Sorry @bigown, I was editing my comment and then I noticed that I exceeded the character limit. A simpler way (for me) of perceiving would be: - In the first case the method "pegsListaPessoas" is always executed with each interaction? Because if it is not executed in each interaction, and implicitly it is created a temporary reference to the returned list, then the two forms would be very similar , I believe. On the other hand, the implementation of the "pegaListaPessoas()" method turns out to be not the most important in this analysis (in my opinion), and in the comments I suggested that BD (example only).

  • @Coldhack And that’s exactly what I wrote. You’re thinking the problem is that I gave you more details?

  • Once again I am grateful for the sweet explanation. And I did not say that the details are a problem, but rather, the analysis of the implementation of the method that returns the list. So much so that I recognized and said that I understood your point. As for the illustrious example, it was only to show him how the question could be perceived (and indeed that was how he also understood it). In short, both can theoretically (I say this because I never compared in practice) consume the same resources and take the same running time. Thank you for your attention @bigown and for your detailed responses.

  • @Coldhack unfortunately I’m not understanding where you’re going with this.

  • @Coldhack The initialization of for is executed only once, if this doubt still remains.

  • After the exposure of the very expensive <<bigown>, this became very clear. I just thought someone that there might still be other factors that differentiate the two forms. Thank you @bfavaretto

Show 3 more comments

Browser other questions tagged

You are not signed in. Login or sign up in order to post.