我有两个foreach
循环。其中一个包含唯一电子邮件列表(外部)。我希望将其作为外循环,并在每次外循环元素与内循环之间存在匹配时将计数增加一。
我的代码现在:
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
。
答案 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
}
}
如果它太慢,那么你会想要某种地图来缓存它,这可能在Contact类之外。
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
答案 1 :(得分: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
,这样可以确保我不会多次执行相同的操作。没有必要。