Gee*_*eek 30 java performance findbugs
请参考以下方法:
public Set<LIMSGridCell> getCellsInColumn(String columnIndex){
Map<String,LIMSGridCell> cellsMap = getCellsMap();
Set<LIMSGridCell> cells = new HashSet<LIMSGridCell>();
Set<String> keySet = cellsMap.keySet();
for(String key: keySet){
if(key.startsWith(columnIndex)){
cells.add(cellsMap.get(key));
}
}
return cells;
}
Run Code Online (Sandbox Code Playgroud)
FindBugs给出了这个警告信息:
" 低效使用keySet迭代器而不是entrySet迭代器 此方法使用从keySet迭代器中检索的键访问Map条目的值.在map的entrySet上使用迭代器更有效,以避免Map .get(key)lookup."
Mat*_*teo 51
您正在检索所有键(访问整个地图),然后对于某些键,您再次访问地图以获取值.
您可以迭代地图以获取地图条目(Map.Entry)(键和值的对)并仅访问地图一次.
Map.entrySet()Map.Entry
使用键和相应的值传递一组s.
for ( Map.Entry< String, LIMSGridCell > entry : cellsMap.entrySet() ) {
if ( entry.getKey().startsWith( columnIndex ) ) {
cells.add( entry.getValue() );
}
}
Run Code Online (Sandbox Code Playgroud)
注意:我怀疑这将是一个很大的改进,因为如果你使用地图条目,你将为每个条目实例化一个对象.我不知道这是否真的比get()
直接调用和检索所需的引用更快.
D. *_*ács 12
如果有人仍然对一个详细的,数字支持的答案感兴趣:是的,你应该使用entrySet()
vs. keySet()
以防你在迭代整个 Map.有关详细数字,请参阅此要点.我使用JMH运行基准测试,以获得Map with Oracle JDK8的默认实现.
主要发现是:迭代keySet
重新查询每个键总是慢一点.一旦你有更大的地图,乘数就会变得很大(例如,ConcurrentSkipListMap
它总是5-10倍;而对于HashMap
s,它不会超过2 倍,高达一百万个条目).
但是,这些仍然是非常小的数字.迭代超过100万条目的最慢方式是a ConcurrentSkipListMap.keySet()
,大约是500-700毫秒; 虽然迭代时间IdentityHashMap.entrySet()
仅为25-30毫秒,但LinkedHashMap.entrySet()
仅落后于40-50毫秒(这并不奇怪,因为它LinkedList
内部有一个,这有助于迭代).作为上述链接Gist的概述:
Map type | Access Type | ? for 1M entries
----------------------+-------------+-----------------
HashMap | .entrySet() | 69-72 ms
HashMap | .keySet() | 86-94 ms
ConcurrentHashMap | .entrySet() | 72-76 ms
ConcurrentHashMap | .keySet() | 87-95 ms
TreeMap | .entrySet() | 101-105 ms
TreeMap | .keySet() | 257-279 ms
LinkedHashMap | .entrySet() | 37-49 ms
LinkedHashMap | .keySet() | 89-120 ms
ConcurrentSkipListMap | .entrySet() | 94-108 ms
ConcurrentSkipListMap | .keySet() | 494-696 ms
IdentityHashMap | .entrySet() | 26-29 ms
IdentityHashMap | .keySet() | 69-77 ms
Run Code Online (Sandbox Code Playgroud)
所以底线是:它取决于你的用例.虽然迭代的速度肯定更快,entrySet()
但数字并不大,特别是对于相当小的地图.但是,如果你经常迭代一个包含100万个条目的Map,那么最好使用更快的方式;)
当然,这些数字只是为了相互比较,而不是绝对的.
您将获得地图中的一组键,然后使用每个键从地图中获取值.
相反,您可以简单地遍历通过返回给您的Map.Entry键/值对entrySet()
.这样你就可以避免相对昂贵的get()
查询(请注意在这里使用相对的单词)
例如
for (Map.Entry<String,LIMSGridCell> e : map.entrySet()) {
// do something with...
e.getKey();
e.getValue();
}
Run Code Online (Sandbox Code Playgroud)