たまにSetを返すフレームワークに出会ったとき、Setから特定の要素を取り出したいケースがあります。
Setは本来そのような使い方をするものではないのですが、たとえばSeleniumのCookieを保存しておいて適切なときに取り出したい、という場合があります。
SetをMapに変換する
Set<Cookie> cookies = driver.getCookies();
// key : valueの形にしたい場合
Map<String, String> cookieMap = cookies.stream().collect(Collectors.toMap(Cookie::getName, Cookie::getValue));
// key : Cookieの形にしたい場合
Map<String, Cookie> cookieMap = cookies.stream().collect(Collectors.toMap(Cookie::getName, c->c));
Setのまま使っちゃだめなの?
Setは、重複した要素がないことを保証するクラスですが、実は中身はMapだったりします。
件のSeleniumにはgetCookieNamedという便利メソッドがありますが、その実装がこちらです。
public Cookie getCookieNamed(String name) {
Set<Cookie> allCookies = getCookies();
for (Cookie cookie : allCookies) {
if (cookie.getName().equals(name)) {
return cookie;
}
}
return null;
}
これを見ると、毎回全件見に行っていることがわかります。とはいえCookieはそんな大量に使うものでもありませんから、パフォーマンス上の問題が出ることはそうそうありませんが、プログラマとしては少々気になるところです。
何らかの理由でSetを利用する場合は、その特性を十分意識して利用するようにしましょう。
まとめ
Setに限らず、Java8から導入されたStreamインターフェースを利用すれば、様々な処理が簡単に実現できます。特にMapやListとの相互変換はよく使いますから、覚えておいて適切なときに使えるとよいですね。