【Java】SetをMapに変換する

 たまに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との相互変換はよく使いますから、覚えておいて適切なときに使えるとよいですね。