私は ScalaTest から Java コードを単体テストしており、宣言された同じステートメント内に java.util.HashMap を設定したいと考えています。Scalaでこれを行うことは可能ですか?
5 に答える
これを達成するためのさまざまな方法がたくさんありますが、これまでの回答にはそのうちのいくつかしか表示されていません.
方法 1:java.util.HashMap
constructor があるためHashMap(Map<? extends K,? extends V> m)
、有効な Java Map を渡すことができます。そして、これは Scala の help を使って簡単に行うことができますJavaConversions
:
scala> import scala.collection.JavaConversions._
import scala.collection.JavaConversions._
scala> val myMap = Map(1->"Hi",2->"Bye")
myMap: scala.collection.immutable.Map[Int,java.lang.String] = Map((1,Hi), (2,Bye))
scala> val jmap = new java.util.HashMap[Int,String](myMap) // Need explicit types
jmap: java.util.HashMap[Int,String] = {1=Hi, 2=Bye}
ここでの欠点は、既に Scala マップを持っている必要があること (おそらく Java マップを作成するだけなら、少し無駄です) と、型を指定する必要があることです。でもコンパクトで痛くない。
方法 2:別の方法として、宣言ステートメントとして新しいコード ブロックを作成することもできるため、使用可能にする必要さえありませんJavaConversions
。
scala> val jmap2 = {
| val x = new java.util.HashMap[Int,String]
| for ((k,v) <- List(1->"Howdy",2->"partner")) x.put(k,v)
| x
| }
jmap2: java.util.HashMap[Int,String] = {1=Howdy, 2=partner}
少しコンパクトではありませんが、完全に一般的であり、作成したいのと同じくらい効率的 (または非効率的) です。
方法 3:.getClass
また、サブクラスを使用してもよい (つまり、を返さない)限り、HashMap の匿名サブクラスを作成しjava.util.HashMap
、初期化子を使用して値を設定することもできます。
scala> val jmap3 = new java.util.HashMap[Int,String] {
| put(1,"Yo"); put(2,"bro")
| }
jmap3: java.util.HashMap[Int,String] = {1=Yo, 2=bro}
scala> jmap3.getClass.getName
res0: java.lang.String = $anon$1
scala> jmap3.getClass.getSuperclass.getName
res1: java.lang.String = java.util.HashMap
もちろん、欠点は ではHashMap
なくのサブクラスでHashMap
あることですが、新しいマップを val に割り当てる必要がないため、コード ブロックからの割り当てバージョンよりもコンパクトです。
方法 4:そして最後に、もちろん、必要なことを実行するメソッドを作成して、代わりに呼び出すことができます。
scala> def newJHM[A,B](kv: Iterable[(A,B)]) = {
| val jhm = new java.util.HashMap[A,B]
| kv.foreach(i => jhm.put(i._1,i._2))
| jhm
| }
newJHM: [A,B](kv: Iterable[(A, B)])java.util.HashMap[A,B]
scala> val jmap4 = newJHM(Seq(1->"Bye",2->"Now")) // Type inference now works
jmap4: java.util.HashMap[Int,java.lang.String] = {1=Bye, 2=Now}
これは他のものよりもかろうじてコンパクトであり、型を指定しなくても正しい型を取得できるため、これを複数回行う場合には魅力的な選択肢となる可能性があります。
PS 楽しみのために、いくつかのキーと値のペアをマップに取得するさまざまな方法を示しましたが、それらは特定の方法に固有のものではありません (マップを必要とする #1 を除く)。お好みで組み合わせてください。
匿名クラスとしてマップを実行し、オブジェクトのインスタンス初期化の一部として初期化を実行できます。
import java.util.HashMap
val jhm = new HashMap[String, Int](){
put(key1, value1)
put(key2, value2)
}
これは実際には Java でも同じように機能しますが (二重中括弧 {{}} が必要な場合を除く)、Scala ではより慣用的です。
Randallの答えに基づいJavaConversions
て、少し助けるために使用できます。
import collection.JavaConversions.asMap
import java.util.HashMap
val jhm = new HashMap[Int,String](Map(1->"one", 2->"two"))
もちろん、すべてのメソッドとコンストラクターをjava.util.HashMap
使用できますが、初期値を提供する別のマップがない限り、マップを初期化する方法は提供されません。おそらく最も近いものは次のとおりです。
import java.util.HashMap
val jhm = new HashMap[String, Int]
«code to add key-value pairs to jhm»
何かを再利用可能にするために、初期化構文のためだけに新しい「マップ」サブタイプを作成することが可能です。
これは次のように機能する可能性があります(ジェネリックを定期的に使用していないため、ジェネリックを無視しています。おそらく何か問題が発生する可能性があります)。
HashMap hm=new HashMap(
new InitMap(
new String[]{"one", "two", "three"},
new int[] { 1 , 2 , 3 };
)
);
InitMapクラスにはさらに多くのコードが含まれますが、再利用可能でかなり簡単です(この種のものの配列初期化構文が本当に好きです)。
それについて考えると、InitMapクラスはそれほど難しくはありません。おそらく、どのメソッドが呼び出されたかを把握し、それらを実装することをお勧めします。KeySetメソッドとEntrySetメソッドのみを呼び出す可能性があります。
もちろん、このレートでは、2つの配列を取得してHashMapを返すヘルパーメソッドを簡単に作成するか、HashMapを拡張して新しいコンストラクターを追加することができます...