Tôi thấy mình sử dụng rất nhiều bản đồ lồng nhau, ví dụ Map [Int, Map [String, Set [String]]] và tôi muốn có Maps, Sets mới, vv được tạo tự động khi tôi truy cập một khóa mới. Ví dụ. giống như sau:Thiết kế bản đồ có giá trị mặc định thuận tiện trong Scala
val m = ...
m(1992)("foo") += "bar"
Lưu ý rằng tôi không muốn sử dụng getOrElseUpdate đây nếu tôi không phải vì nó được khá dài dòng khi bạn đã lồng bản đồ và che khuất những gì đang thực sự xảy ra trong các mã:
m.getOrElseUpdate(1992, Map[String, Set[String]]()).getOrElseUpdate("foo", Set[String]()) ++= "bar"
Vì vậy, tôi sẽ ghi đè phương pháp "mặc định" của HashMap. Tôi đã thử hai cách để làm điều này, nhưng không phải là hoàn toàn thỏa đáng. giải pháp đầu tiên của tôi là viết một phương pháp mà tạo ra bản đồ, nhưng có vẻ như tôi vẫn phải xác định đầy đủ lồng Loại bản đồ khi tôi khai báo biến hoặc những thứ không làm việc:
scala> def defaultingMap[K, V](defaultValue: => V): Map[K, V] = new HashMap[K, V] { | override def default(key: K) = {
| val result = defaultValue
| this(key) = result
| result
| }
| }
defaultingMap: [K,V](defaultValue: => V)scala.collection.mutable.Map[K,V]
scala> val m: Map[Int, Map[String, Set[String]]] = defaultingMap(defaultingMap(Set[String]()))
m: scala.collection.mutable.Map[Int,scala.collection.mutable.Map[String,scala.collection.mutable.Set[String]]] = Map()
scala> m(1992)("foo") += "bar"; println(m)
Map(1992 -> Map(foo -> Set(bar)))
scala> val m = defaultingMap(defaultingMap(Set[String]()))
m: scala.collection.mutable.Map[Nothing,scala.collection.mutable.Map[Nothing,scala.collection.mutable.Set[String]]] = Map()
scala> m(1992)("foo") += "bar"; println(m)
<console>:11: error: type mismatch;
found : Int(1992)
required: Nothing
m(1992)("foo") += "bar"; println(m)
^
giải pháp thứ hai của tôi là để viết một lớp nhà máy với một phương pháp, và theo cách đó tôi chỉ phải khai báo từng loại một lần. Nhưng sau đó mỗi khi tôi muốn có một mặc định bản đồ mới có giá trị, tôi phải cả hai nhanh chóng lớp nhà máy và sau đó gọi phương thức, mà vẫn có vẻ hơi dài dòng:
scala> class Factory[K] {
| def create[V](defaultValue: => V) = new HashMap[K, V] {
| override def default(key: K) = {
| val result = defaultValue
| this(key) = result
| result
| }
| }
| }
defined class Factory
scala> val m = new Factory[Int].create(new Factory[String].create(Set[String]()))
m: scala.collection.mutable.HashMap[Int,scala.collection.mutable.HashMap[String,scala.collection.mutable.Set[String]]] = Map()
scala> m(1992)("foo") += "bar"; println(m)
Map(1992 -> Map(foo -> Set(bar)))
Tôi thực sự muốn có một cái gì đó đơn giản như thế này:
val m = defaultingMap[Int](defaultingMap[String](Set[String]()))
Bất kỳ ai cũng có cách để làm điều đó?
Tôi thấy, lừa là sử dụng một lớp đối tượng đi kèm ở trên cùng của lớp nhà máy. Cảm ơn, rất tuyệt! Ngoài sự tò mò, bạn sẽ sử dụng API nào? Tôi đang cố gắng tránh sự tàn bạo getOrElseUpdate lồng nhau tôi đã cho thấy trong khối mã thứ hai ở trên. Tôi chắc chắn sẽ mở ra những cách khác để làm điều đó. – Steve