[英]Java optimization, gain from hashMap?
我已經給出了一些可愛的 Java代碼,其中包含很多類似的內容(一個循環執行約150萬次)。
code = getCode();
for (int intCount = 1; intCount < vA.size() + 1; intCount++)
{
oA = (A)vA.elementAt(intCount - 1);
if (oA.code.trim().equals(code))
currentName= oA.name;
}
從切換到以下內容后,我是否會看到速度顯着提高
code = getCode();
//AMap is a HashMap
strCurrentAAbbreviation = (String)AMap.get(code);
編輯:VA的大小約為50.裝飾甚至不應該是必要的,但肯定會是不錯的調用50倍,而不是50 * 150萬。 vA中的項目是唯一的。
編輯:在幾個響應者的建議下,我對其進行了測試。 結果在底部。 多謝你們。
只有一種找出方法。
好吧,好吧,我測試了一下。
結果說明如下:
循環:18391ms散列:218ms
循環:18735ms哈希:234ms
循環:18359ms哈希:219ms
我想我會重構一下..
框架:
public class OptimizationTest {
private static Random r = new Random();
public static void main(String[] args){
final long loopCount = 1000000;
final int listSize = 55;
long loopTime = TestByLoop(loopCount, listSize);
long hashTime = TestByHash(loopCount, listSize);
System.out.println("Looping: " + loopTime + "ms");
System.out.println("Hash: " + hashTime + "ms");
}
public static long TestByLoop(long loopCount, int listSize){
Vector vA = buildVector(listSize);
A oA;
StopWatch sw = new StopWatch();
sw.start();
for (long i = 0; i< loopCount; i++){
String strCurrentStateAbbreviation;
int j = r.nextInt(listSize);
for (int intCount = 1; intCount < vA.size() + 1; intCount++){
oA = (A)vA.elementAt(intCount - 1);
if (oA.code.trim().equals(String.valueOf(j)))
strCurrentStateAbbreviation = oA.value;
}
}
sw.stop();
return sw.getElapsedTime();
}
public static long TestByHash(long loopCount, int listSize){
HashMap hm = getMap(listSize);
StopWatch sw = new StopWatch();
sw.start();
String strCurrentStateAbbreviation;
for (long i = 0; i < loopCount; i++){
int j = r.nextInt(listSize);
strCurrentStateAbbreviation = (String)hm.get(j);
}
sw.stop();
return sw.getElapsedTime();
}
private static HashMap getMap(int listSize) {
HashMap hm = new HashMap();
for (int i = 0; i < listSize; i++){
String code = String.valueOf(i);
String value = getRandomString(2);
hm.put(code, value);
}
return hm;
}
public static Vector buildVector(long listSize)
{
Vector v = new Vector();
for (int i = 0; i < listSize; i++){
A a = new A();
a.code = String.valueOf(i);
a.value = getRandomString(2);
v.add(a);
}
return v;
}
public static String getRandomString(int length){
StringBuffer sb = new StringBuffer();
for (int i = 0; i< length; i++){
sb.append(getChar());
}
return sb.toString();
}
public static char getChar()
{
final String alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
int i = r.nextInt(alphabet.length());
return alphabet.charAt(i);
}
}
嗯,是的,您很有可能會。 如果您具有良好的哈希碼,則從HashMap檢索將是恆定時間。
但是,您真正要找出的唯一方法就是嘗試一下。
這取決於您的地圖有多大,以及hashCode實現的良好程度(這樣您就不會有大腸菌病)。
您實際上應該進行一些實際的分析,以確保是否需要進行任何修改,因為您可能最終會花費時間來修復未損壞的問題。
在我看來,真正要比elementAt調用突出的是每次迭代所進行的字符串修剪。 我的直覺告訴我,這可能是一個更大的瓶頸,但只有剖析才能真正看出來。
祝好運
我會說是的,因為以上內容似乎是對vA.size()的線性搜索。 VA多大?
為什么不使用類似YourKit之類的東西(或插入另一個探查器)來查看循環這部分的成本。
使用Map當然是一項改進,有助於以后維護該代碼。
是否可以使用地圖取決於(vector?)是否包含唯一代碼。 給定的for循環會記住給定代碼的列表中的最后一個對象,這意味着哈希不是解決方案。
對於較小(穩定)的列表大小,僅將列表轉換為對象數組即可在提高可讀性的基礎上提高性能。
如果以上條件均不成立,請至少使用itarator檢查列表,以提高可讀性並提高性能。
要看。 你有多少內存?
我想速度要快得多,但是要對其進行分析。
我認為這里的主要因素是vA有多大,因為循環需要運行n次,其中n是vA的大小。 有了地圖,無論vA有多大,都沒有循環。 因此,如果n小,則改善將很小。 如果規模巨大,那么改善將是巨大的。 這是特別正確的,因為即使找到匹配的元素,循環仍然繼續! 因此,如果您在200萬個元素列表的元素1中找到匹配項,則仍然需要檢查最后1,999,999個元素!
是的,幾乎可以肯定會更快。 假設您的vA內容可以很好地散列,則平均循環25次(遍歷50次)要比散列圖查找慢。
但是,說到vA內容 ,將它們插入aMap時必須修剪它們,因為aMap.get(“ somekey”)不會找到鍵為“ somekey”的條目。
實際上,即使您不切換到哈希圖解決方案,也應該在插入vA時這樣做。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.