简体   繁体   中英

Replace more complex nested for loops with Java 8 streams

My loops are more complex than normally and before I even try harder to implement it I would like to hear whether it's possible.

if (emailClicks != null  && emailsOfContactsWhoFitDynConFilter != null) {
            for (String email : emailsOfContactsWhoFitDynConFilter) {
                for (Contact contact : emailClicks.items) { 
                    String queryStringActivity = getQueryStringByName("elqTrackId", (contact.link).split("\\?",-1)[1]);
                    String queryStringDynConLink = getQueryStringByName("elqTrackId", linkInDynamicContent.split("\\?",-1)[1]);
                    if (email.equals(contact.EmailAddress) && (contact.link).split("\\?")[0].equals(linkInDynamicContent.split("\\?")[0])) {
                        if (queryStringActivity !=null && queryStringDynConLink!=null && queryStringActivity.equals(queryStringDynConLink)){
                            count++;
                            break; 
                        }else if (queryStringActivity==null || queryStringDynConLink ==null){
                            count++;
                            break;
                        }
                    }
                }
            }
        }

Perhaps you might help me to optimize it with some other method. I just experience extreme time consumption here when arrays are too big (approx. 20 000)

  • As already mentioned in the comments: linkInDynamicContent.split("\\\\?",-1) can be done once outside of both loops as linkInDynamicContent never changes
  • You split your contact.link which takes time and then don't use it, if this condition if (email.equals(contact.EmailAddress) fails.

    The biggest problem I see is, that you are basically doing a "nested loop join" for email join contact on email.id = contact.email which has a runtime of n * m for n being the amount of emails and m the amount of contacts.
    And you don't use the email after all. You you do your inner loop for every combination of email and contact. But only one time, when the contact.email matcher your email from the first loop you actually do something.
    Try changing your structure to something like this:

     String[] linkInDynamicContentSplit = linkInDynamicContent.split("\\\\?",-1); if (!emailsOfContactsWhoFitDynConFilter.isEmpty()) { for (Contact contact : emailClicks.items) { if(emailsOfContactsWhoFitDynConFilter.contains(contact.EmailAddress)); // your code String queryStringActivity = getQueryStringByName("elqTrackId", (contact.link).split("\\\\?",-1)[1]); // ... } } 
  • Never include in a loop operation that can be done outside it. (already mentioned)

  • Look where you duplicate your code or check the same condition more than once

if(queryStringActivity !=null && ....)

.....

else if(queryStringActivity==null || ...))

  • Don't be afraid to create new methods (JIT can inline methods) so there will be no efficiency loss

  • Try to use recursion instead of iteration (recursion is from God, iteration from programmer) (It's a pity that even Java8 lacks tail recursion, but it is a good practice).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM