2010-09-06 44 views
29

Tôi có HashMap có thể thay đổi và muốn sử dụng nó như một từ điển mặc định. Phương pháp hiển nhiên dường như sử dụng getOrElse và cung cấp giá trị mặc định mỗi lần làm giá trị thứ hai. Tuy nhiên điều này có vẻ hơi không phù hợp trong trường hợp sử dụng của tôi vì giá trị mặc định không thay đổi.Scala: Sử dụng HashMap với giá trị mặc định

var x = HashMap(1 -> "b", 2 -> "a", 3 -> "c") 

println(x.getOrElse(4, "_") 
println(x.getOrElse(5, "_")) 
// And so on... 
println(x.getOrElse(10, "_")) 

Có cách nào để tạo HashMap (hoặc lớp tương tự) để cố gắng truy cập các khóa không xác định trả về giá trị mặc định được thiết lập khi tạo HashMap không? Tôi nhận thấy rằng HashMap.default chỉ được thiết lập để ném một ngoại lệ nhưng tôi tự hỏi nếu điều này có thể được thay đổi ...

+5

Để bất cứ ai tình cờ gặp câu hỏi này, bài missingfaktor của khẳng định một cách chính xác rằng "Scala 2.9.1 mutable.Map đi kèm với một phương pháp withDefaultValue." – wynnch

Trả lời

34

Hãy thử điều này:

import collection.mutable.HashMap 
val x = new HashMap[Int,String]() { override def default(key:Int) = "-" } 
x += (1 -> "b", 2 -> "a", 3 -> "c") 

Sau đó:

scala> x(1) 
res7: String = b 

scala> x(2) 
res8: String = a 

scala> x(3) 
res9: String = c 

scala> x(4) 
res10: String = - 
+4

+1. Tự hỏi tại sao 'mutable.HashMap' không cung cấp phương thức' withDefaultValue' như 'immutable.HashMap'. – missingfaktor

+2

Đó là cú pháp khủng khiếp, nhưng nó là thủ thuật. Có lẽ thiếu withDefaultValue cho HashMaps có thể thay đổi được báo cáo là lỗi? –

+4

Có một "todo: di chuyển đến bản đồ chung?" nhận xét trong 'withDefault' lân cận trong http://www.scala-lang.org/api/current/scala/collection/immutable/Map.html. Vì vậy, có thể đây không phải là quá nhiều của một căng.Danh sách gửi thư scala-user có lẽ là một nơi tốt để hỏi về điều này và xem có nên báo cáo lỗi hay không. – huynhjl

1
scala> val x = HashMap(1 -> "b", 2 -> "a", 3 -> "c").withDefaultValue("-") 
x: scala.collection.immutable.Map[Int,java.lang.String] = Map((1,b), (2,a), (3,c)) 

scala> x(3) 
res0: java.lang.String = c 

scala> x(5) 
res1: java.lang.String = - 

EDIT:

Đối mutable.HashMap, bạn có thể làm như sau:

scala> import collection.mutable 
import collection.mutable 

scala> val x = new mutable.HashMap[Int, String] { 
    | override def apply(key: Int) = super.get(key) getOrElse "-" 
    | } 
x: scala.collection.mutable.HashMap[Int,String] = Map() 

scala> x += (1 -> "a", 2 -> "b", 3 -> "c") 
res9: x.type = Map((2,b), (1,a), (3,c)) 

scala> x(2) 
res10: String = b 

scala> x(4) 
res11: String = - 

Có thể có cách tốt hơn để thực hiện việc này. Đợi người khác trả lời.

+0

Đó chỉ xuất hiện để làm việc với HashMaps không thay đổi. –

+1

@PythonPower: Bạn đã không chỉ định nó trong câu hỏi ban đầu của bạn mà bạn đang sử dụng 'mutable.HashMap'. Tôi không biết làm thế nào để làm điều đó với 'mutable.HashMap'. Tôi sẽ phải xem xét API. – missingfaktor

+0

Có, xin lỗi tôi đã không chỉ định - Tôi đã chỉnh sửa câu hỏi của mình để làm rõ ngay bây giờ. –

0

tôi hơn một chàng trai java ... nhưng nếu getOrElse không phải là cuối cùng, tại sao bạn không chỉ mở rộng HasMap và cung cấp một cái gì đó như thế này:

override def getOrElse(k: Int, default: String) = { 
    return super.getOrElse(k,"_") 
} 

Lưu ý: Cú pháp có lẽ là hơi say lên nhưng hy vọng bạn sẽ nhận được điểm

+0

Có, tôi nghĩ rằng có thể mở rộng HashMap. Trong trường hợp đó, có lẽ sẽ dễ dàng hơn để thay đổi phương thức HashMap.default để trả lại những gì tôi muốn. Hàm khởi tạo có thể lấy giá trị mặc định và phương thức HashMap.default sẽ trả về giá trị đó. Tôi hy vọng có một phương pháp dễ dàng hơn, tuy nhiên. –

+0

Chúng tôi không làm điều này bc nó phức tạp hơn 'getOrElse' - nó có ít linh hoạt hơn, không cần thiết, và nếu bạn * phải * làm điều này, là dấu hiệu mạnh mẽ bạn nên sử dụng một số trừu tượng mức cao, như monoids . – BAR

67

Ồ, tôi đã xảy ra để truy cập chủ đề này chính xác một năm sau khi tôi đăng câu trả lời cuối cùng của mình ở đây. :-)

Scala 2.9.1. mutable.Map đi kèm với phương thức withDefaultValue. REPL phiên:

scala> import collection.mutable 
import collection.mutable 

scala> mutable.Map[Int, String]().withDefaultValue("") 
res18: scala.collection.mutable.Map[Int,String] = Map() 

scala> res18(3) 
res19: String = "" 
+0

Điều này phải được đánh dấu là câu trả lời đúng –

+0

Tôi lo ngại về hiệu suất cho việc này - không thể sử dụng được.Bạn có thể sử dụng HashMaps không? Hiệu suất của nó như thế nào? –

Các vấn đề liên quan