Ответ 1
Почему бы не использовать withDefaultValue (значение)?
scala> val m = Map[Int, List[String]]().withDefaultValue(List())
m: scala.collection.immutable.Map[Int,List[String]] = Map()
scala> m(123)
res1: List[String] = List()
class DefaultListMap[A, B <: List[B]] extends HashMap[A, B] {
override def default(key: A) = List[B]()
}
Я не буду создавать карту A -> List[B]
. В моем случае это Long -> List[String]
, но когда я получаю ключ от карты, у которой нет значения, я хотел бы создать пустой List
вместо Exception
. Я пробовал разные комбинации, но я не знаю, как сделать код выше, передав компилятор.
Спасибо заранее.
Почему бы не использовать withDefaultValue (значение)?
scala> val m = Map[Int, List[String]]().withDefaultValue(List())
m: scala.collection.immutable.Map[Int,List[String]] = Map()
scala> m(123)
res1: List[String] = List()
Вместо того, чтобы использовать apply
для доступа к карте, вы всегда можете использовать get
, который возвращает Option[V]
, а затем getOrElse
:
map.get(k) getOrElse Nil
Одной из замечательных особенностей функционально-программируемой библиотеки scalaz является унарный оператор ~
, что означает "или ноль", если тип значения имеет "нуль", определенный (который List
, нуль, конечно, Nil
). Таким образом, код становится следующим:
~map.get(k)
Это вдвойне полезно, потому что тот же синтаксис работает там, где (например) ваши значения Int
, Double
и т.д. (все, для которых существует класс Zero
).
В списке рассылки scala было много обсуждений об использовании Map.withDefault
из-за того, как это происходит, в частности, в отношении метода isDefinedAt
. По этой причине я стараюсь избегать этого.
Есть метод withDefaultValue
на Map
:
scala> val myMap = Map(1 -> List(10), 2 -> List(20, 200)).withDefaultValue(Nil)
myMap: scala.collection.immutable.Map[Int,List[Int]] = Map((1,List(10)), (2,List(20, 200)))
scala> myMap(2)
res0: List[Int] = List(20, 200)
scala> myMap(3)
res1: List[Int] = List()
Почему вы хотите манипулировать картой, если у нее уже есть метод для этого?
val m = Map(1L->List("a","b"), 3L->List("x","y","z"))
println(m.getOrElse(1L, List("c"))) //--> List(a, b)
println(m.getOrElse(2L, List("y"))) //--> List(y)
withDefault.
/** The same map with a given default function.
* Note: `get`, `contains`, `iterator`, `keys`, etc are not affected
* by `withDefault`.
*
* Invoking transformer methods (e.g. `map`) will not preserve the default value.
*
* @param d the function mapping keys to values, used for non-present keys
* @return a wrapper of the map with a default value
*/
def withDefault[B1 >: B](d: A => B1): immutable.Map[A, B1]
Пример:
scala> def intToString(i: Int) = s"Integer $i"
intToString: (i: Int)String
scala> val x = Map[Int, String]().withDefault(intToString)
x: scala.collection.immutable.Map[Int,String] = Map()
scala> x(1)
res5: String = Integer 1
scala> x(2)
res6: String = Integer 2
Надеюсь, что это поможет.