↓のようにkeyしか使用しないコードでもfindbugsでentrySet()を使えと警告がでた。
for(var key : map.keySet()){
// map.get(key)などやらず、純粋にkeyしか使用しない処理
}
keyとvalue 両方使用するならentrySet()のほうが効率が良いのと解釈していたので、片方のみ使用する場合は効率に関係ないのでは?
むしろ、Entry<K,V>はkeyとvalue両方持つので不要な片方のリソースが無駄ではないのかと思い、裏取りのため内部実装を見てみる。
AbstractMap.java
public Set<K> keySet() {
Set<K> ks = keySet;
if (ks == null) {
ks = new AbstractSet<K>() {
public Iterator<K> iterator() {
return new Iterator<K>() {
private Iterator<Entry<K,V>> i = entrySet().iterator();
// 略
};
}
};
keySet = ks;
}
return ks;
}
keySetが無ければ作り出してフィールドに保持するようになっているが、Iterator<K>の初期化にentrySet().iterator()を呼び出していることがわかる。
結局のところkeySet()やvalues()ではentrySet()を通してごにょる様子。
つまり、keyまたはvalueの片方のみであっても思考停止でentrySet()を使用したほうがいいという警告は正しかったのである。