Help us understand the problem. What is going on with this article?

JavaでもScalaでも便利で重宝するMultiMap

More than 5 years have passed since last update.

はじめに

Mapの値型にSeq、Set、Listあたりを取るときにありがちなコード。
キーが無かったらコレクションをnewして・・・という部分を書くのがかったるい。
※scala.mutable.Seqなどは値の追加をすると新しいコレクションが返ってきてしまうのでここではListBufferを使った。

val m = mutable.Map.empty[Int, ListBuffer[String]]

def addKeyValue(k: Int, v: String) = {
  if (!m.contains(k)) {
    m += (k -> new ListBuffer[String])
  }

  m(k) += v
}

MultiMapでリファクタリング

こんな時は、scala.collection.mutable.MultiMapを使うとスッキリ書ける。
MultiMapはtraitであり、具象クラスが用意されていないので以下のようにmix-inして使うのが基本となる。

val m = new mutable.HashMap[Int, mutable.Set[String]] with mutable.MultiMap[Int, String]

def addKeyValue(k: Int, v: String) = m.addBinding(k, v)

但し、MultiMapの値はSet型になるので注意が必要だ。以下のように宣言されている。
TreeSetのような順序を保持できるSetを使うことも出来ない。

trait MultiMap[A, B] extends Map[A, Set[B]] {

自作するにしても、MultiMapのソースコードはたかだかこの程度でありそんなに難しいものでもないだろう。

おまけ

なお、最初のコードは以下のようにMap#getOrElseUpdateメソッドを使うことでもう少し簡潔に書くことも出来る。

val m = mutable.Map.empty[String, ListBuffer[String]]

def addKeyValue(k: String, v: String) = {
  val l = m.getOrElseUpdate(k, new mutable.ListBuffer[String])
  l += v
}

Java編

あと、Javaでは標準ライブラリには存在しないものの、Google製guavaライブラリには同名のMultiMapが存在する。
同様にif文が不要になり重宝する。

Multimap<Int, String> m = ArrayListMultimap.create();
m.put(1, "one");
Why do not you register as a user and use Qiita more conveniently?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away