祝大家度过美好的一天。
我的代码可以完成Excel Pivot在几秒钟内所做的工作。然而,我的代码在不少于30分钟内做同样的事情。我对这种差异感到震惊!我很确定我可以优化我的代码,使其比目前更快。任何帮助将受到高度赞赏。
请快速查看代码。如有必要,我会详细解释它究竟是做什么的。谢谢!
public void countImages(ArrayList<String> all) throws IOException {
HashSet<String> uStrings = new HashSet<>();
int Counter = 0;
int C500x500 = 0;
int C800x800 = 0;
int C1000x1000 = 0;
int G1000x1000 = 0;
write("Vendor ID, Count of Images, Less than 500 x 500, Less than 800 x 800, Less than 1000 x 1000, Greater than 1000 x 1000", "ImageCount_Data");
for (String single : all) {
String[] linearray = single.split(",");
uStrings.add(linearray[0]);
}
totallines = uStrings.size();
completedlines = 0;
percentage = 0;
setPercent(0);
for (String uString : uStrings) {
Counter = 0;
C500x500 = 0;
C800x800 = 0;
C1000x1000 = 0;
G1000x1000 = 0;
for (String single : all) {
String[] linearray = single.split(",");
if (linearray[0].equals(uString)) Counter++;
if ((linearray[1].equals("Less than 500 x 500")) && linearray[0].equals(uString)) C500x500++;
if ((linearray[1].equals("Less than 800 x 800")) && linearray[0].equals(uString)) C800x800++;
if ((linearray[1].equals("Less than 1000 x 1000")) && linearray[0].equals(uString)) C1000x1000++;
if ((linearray[1].equals("Greater than 1000 x 1000")) && linearray[0].equals(uString)) G1000x1000++;
} //END OF 2ND FOR LOOP
write(uString + "," + Counter + "," + C500x500 + "," + C800x800 + "," + C1000x1000 + "," + G1000x1000, "ImageCount_Data");
completedlines++;
percentage = (completedlines / totallines) * 100;
setPercent(Math.round(percentage));
Icwindow.frame.setTitle("Writing Image Count Data: " + getPercent() + "%");
} //END OF 1ST FOR LOOP
Icwindow.frame.setTitle("Process Cloudinary ImageCount Data");
}
答案 0 :(得分:1)
您正在遍历列0中的所有可能字符串,然后在该循环内再次遍历所有字符串。因此,您的算法为O(n²),其中Excel可以通过更快(可能是O(n)摊销)的算法获得。
您可以使用HashMap<String, Counts>
来跟踪计数,只使用一个for循环而不是两个嵌套循环。
Counts
对象将包含您的类的计数,如:
class Counts {
int c500;
int c800;
int c1000;
int cOther;
void count(String s) {
switch(s) {
case "Less than 500 x 500": c500++; break;
case "Less than 500 x 500": c800++; break;
case "Less than 500 x 500": c1000++; break;
case "Greater than 1000 x 1000": cOther++; break;
default: throw new AssertionError();
}
}
}
另一个提示:您可以通过添加c500 + c800 + c1000 + cOther
来获取全局计数器。
答案 1 :(得分:0)
非常感谢你!
下面是我使用Hash Map的新代码,它确实比我之前的代码快得多。但是,代码中似乎存在不正确的原因,因为计数仅对第一个哈希映射是正确的,其余4映射具有不正确的计数。我可以请你看看并告诉我你是否注意到新代码中有什么奇怪的东西?
编辑 - 我错过了在switch case语句中添加中断!这非常有效。快速! :d
public void countImages(ArrayList<String> all) throws IOException {
HashMap<String, Integer> counter = new HashMap<>();
HashMap<String, Integer> c500 = new HashMap<>();
HashMap<String, Integer> c800 = new HashMap<>();
HashMap<String, Integer> c1000 = new HashMap<>();
HashMap<String, Integer> g1000 = new HashMap<>();
write("Vendor ID, Count of Images, Less than 500 x 500, Less than 800 x 800, Less than 1000 x 1000, Greater than 1000 x 1000", "ImageCount_Data");
for (String single : all) {
String[] linearray = single.split(",");
if (!counter.containsKey(linearray[0])) {
counter.put(linearray[0], 1);
} else {
counter.put(linearray[0], counter.get(linearray[0]) + 1);
}
switch (linearray[1]) {
case "Less than 500 x 500" :
if (!c500.containsKey(linearray[0])) {
c500.put(linearray[0], 1);
} else {
c500.put(linearray[0], c500.get(linearray[0]) + 1);
}
case "Less than 800 x 800" :
if (!c800.containsKey(linearray[0])) {
c800.put(linearray[0], 1);
} else {
c800.put(linearray[0], c800.get(linearray[0]) + 1);
}
case "Less than 1000 x 1000":
if (!c1000.containsKey(linearray[0])) {
c1000.put(linearray[0], 1);
} else {
c1000.put(linearray[0], c1000.get(linearray[0]) + 1);
}
case "Greater than 1000 x 1000" :
if (!g1000.containsKey(linearray[0])) {
g1000.put(linearray[0], 1);
} else {
g1000.put(linearray[0], g1000.get(linearray[0]) + 1);
}
}
}
for (String key : counter.keySet()) {
write(key + "," + counter.get(key) + "," + c500.get(key) + "," + c800.get(key) + "," + c1000.get(key) + "," + g1000.get(key), "ImageCount_Data");
}
}