2015-12-17 83 views
1

我有两个foreach循环。其中之一包含唯一电子邮件列表(外部)。我希望将外部循环作为外部循环,并且每次在外部循环的元素与内部循环之间匹配时增加1。如何优化嵌套循环?

我现在代码:

outer: for (String email : emailsOfContactsWhoFitDynConFilter) { 
     for (Contact contact : emailClicks.items) { 
      String[] contactLink = (contact.link).split("\\?", -1); 
      String queryStringActivity = getQueryStringByName("elqTrackId", contactLink[1]); 

      if (email.equals(contact.EmailAddress) && contactLink[0].equals(linkInDynamicContentSplit[0])) { 
       if (queryStringActivity !=null && queryStringDynConLink!=null && queryStringActivity.equals(queryStringDynConLink)){ 
        count++; 
        break outer; 
        } else if (queryStringActivity == null || queryStringDynConLink == null) { 
        System.out.println(" - Missing elqTrackId. But base the same, count++"); 
        count++; 
        break outer; 
       } 
      } 
     } 
    } 

它的工作原理,但问题是这两条线:

String[] contactLink = (contact.link).split("\\?", -1); 
String queryStringActivity = getQueryStringByName("elqTrackId", contactLink[1]); 

被执行过很多次消耗了大量的时间。

我可以扭转的循环,所以它看起来像这样:

outer: for (Contact contact : emailClicks.items) { 
      String[] contactLink = (contact.link).split("\\?", -1); 
      String queryStringActivity = getQueryStringByName("elqTrackId", contactLink[1]); 
      for (String email : emailsOfContactsWhoFitDynConFilter) { 
      if (email.equals(contact.EmailAddress) && contactLink[0].equals(linkInDynamicContentSplit[0])) { 
       if (queryStringActivity !=null && queryStringDynConLink!=null && queryStringActivity.equals(queryStringDynConLink)){ 
        count++; 
        break outer; 
        } else if (queryStringActivity == null || queryStringDynConLink == null) { 
        System.out.println(" - Missing elqTrackId. But base the same, count++"); 
        count++; 
        break outer; 
       } 
      } 
     } 
    } 

那会快很多,但我的count++会发生更多的时间比我想,这不会是+1每一个独立的电子邮件。

+5

我投票关闭这一问题作为题外话,因为这个问题将是一个更适合于:http://codereview.stackexchange.com/ –

+1

为什么'计数++'执行不同的次数?在交叉连接中,您仍然只在每对中检查一次。顺便说一句,如果将标签放在循环的上方,而不是同一行代码,则代码将更易于阅读。如果你将其缩小,你的'else if'行也会更清晰。基本上,缩进使得你的代码现在很难理解。 –

+0

计数会更高,因为内部循环包含不唯一的活动。是否有意义?如果没有,我可以画出来。 –

回答

2

这里有几个很好的选择,但第一个就是简单地缓存String []。这是为什么你应该使用方法而不是成员的宝贵教训。我建议有contact.getLinkCache()方法的方法

,实现像我有以下。这给了你一次又一次的分裂的好处(有一个克隆来保护数据,但克隆是一个非常快的方法,除非你认为这太慢了,你应该用这个。

class Contact { 

    String link; 
    String[] linkSplitCache; 

    public void setLink(String link) { 
     this.link = link; 
     this.linkSplitCache = null; 
    } 

    public String getLink() { 
     return link; 
    } 

    public String[] getLinkCache() { 
     if(linkSplitCache == null) { 
      linkSplitCache = link.split("\\?",-1); 
     } 
     // return linkSplitCache; // could corrupt! 
     return linkSplitCache.clone(); // pretty fast array copy 
    } 
} 

如果实在是太慢了,那么就要某种地图缓存它,这很可能是跟类之外。

Map<Contact, String[]> linkSplitCache = new HashMap<>(); 

outer: for (Contact contact : emailClicks.items) { 
    String[] contactLink = linkSplitCache.get(contact); 
    if(contactLink == null) { 
     contactLink = (contact.link).split("\\?", -1); 
     linkSplitCache.put(contact,contactLink); 
    } 
    // rest of loop here 
+0

我认为你有一个很好的观点,问题在于,'emailClicks.items'作为一个对象在联系方面没有重复。有重复的是两个不同的对象,但共享相同的电子邮件地址。但我想我可以用一些调整来使用你的解决方案。 –

+0

我很高兴你找到了解决方案。但我忍不住想你应该避免使用'object.member' - 而是使用'object.getMember()'。 – corsiKa

+0

是否有任何实际的原因应该通过getter来完成?我知道这是惯例,但仍然有任何真正的原因?由于这些对象只是'JSON'的反序列化,我不使用任何构造函数,所以我并不需要getter。 –

0

与@有很大的帮助corsiKlause Ho Ho Ho我可以来解决:

Map<String, String[]> linkSplitCache = new HashMap<>(); 
    int count = 0; 
    String[] linkInDynamicContentSplit = linkInDynamicContent.split("\\?", -1); 
    String queryStringDynConLink = getQueryStringByName("elqTrackId", linkInDynamicContentSplit[1]); 
    if (emailClicks != null && emailsOfContactsWhoFitDynConFilter != null) { 
     for (String email : emailsOfContactsWhoFitDynConFilter) { 
     inner: for (Contact contact : emailClicks.items) { 
       String[] contactLink = linkSplitCache.get(contact.EmailAddress); 
       if (contactLink == null){ 
        contactLink = (contact.link).split("\\?", -1); 
        contactLink[1] = getQueryStringByName("elqTrackId", contactLink[1]); 
        linkSplitCache.put(contact.EmailAddress, contactLink); 
       } 

       if (email.equals(contact.EmailAddress) && contactLink[0].equals(linkInDynamicContentSplit[0])) { 
        if (contactLink[1] !=null && queryStringDynConLink!=null && contactLink[1].equals(queryStringDynConLink)){ 
         count++; 
         break inner; // this excludes link clicks which were done 
           // twice by the same person 
        } else if (contactLink[1] == null || queryStringDynConLink == null) { 
         System.out.println(" - Missing elqTrackId. But base the same, count++"); 
         count++; 
         break inner; 
        } 
       } 
      } 
     } 
    } 

基本上我所做的是添加链接到HashMap与唯一键Email address,这可以确保我没有做同样的操作不止一次在那里,没有必要了。