Как заполнить java.util.HashMap на лету из кода Scala?

Я занимаюсь модульным тестированием Java-кода из ScalaTest и хотел бы заполнить java.util.HashMap в том же заявлении, в котором он объявлен. Возможно ли сделать это в Scala?

Ответы на вопрос(5)

как часть инициализации экземпляра объекта.

import java.util.HashMap
val jhm = new HashMap[String, Int](){
   put(key1, value1)
   put(key2, value2)
}

На самом деле это работает одинаково хорошо в Java (за исключением необходимости использовать двойные скобки {{}}), но гораздо более идиоматично в Scala.

 EdgeCaseBerg08 сент. 2016 г., 18:09
работал как шарм и легко понять
 Daniel Spiewak03 окт. 2010 г., 20:14
Технически, у Scala нет инициализаторов экземпляров. Код, который вы показываете, выполняетput методы внутриконструктор для анонимного внутреннего класса.
 Dave Griffith03 окт. 2010 г., 20:09
Правильный. редактирование
 Ravinder Payal01 янв. 2018 г., 11:50
Ошибка компиляции: не найдено: значение указано
 Ruediger Keller03 окт. 2010 г., 19:52
Я не думаю, что есть что-то вроде статической инициализации объекта. Я полагаю, вы имеете в виду инициализатор экземпляра, не так ли?

можно создать новый подтип «Карта» только для синтаксиса инициализации.

Это может сработать примерно так (я игнорирую дженерики, потому что я не использую их регулярно, и, возможно, я что-то неправильно):

HashMap hm=new HashMap(
    new InitMap(
        new String[]{"one", "two", "three"},
        new int[]   {  1  ,   2  ,    3   };
    )
);

В классе InitMap будет задействовано больше кода, но он будет многократно использоваться и достаточно прост (мне очень нравится синтаксис инициализации массива для такого рода вещей).

Размышляя об этом, класс InitMap не будет слишком сложным. Возможно, вы захотите выяснить, какие методы были вызваны, и просто реализовать их. Скорее всего, он будет вызывать только методы KeySet и EntrySet.

Конечно, при такой скорости вы можете просто создать вспомогательный метод, который будет принимать два массива и возвращать HashMap или расширять HashMap и добавлять новый конструктор ...

Все методы и конструкторыjava.util.HashMap Конечно, доступны для вас, но это не дает возможности инициализировать карту, если у вас нет другого источника для начальных значений. Самое близкое, что вы, вероятно, собираетесь получить:

import java.util.HashMap
val jhm = new HashMap[String, Int]
«code to add key-value pairs to jhm»

вы можете использоватьJavaConversions немного помочь

import collection.JavaConversions.asMap
import java.util.HashMap
val jhm = new HashMap[Int,String](Map(1->"one", 2->"two"))
Решение Вопроса

только некоторые из которых появились в ответах.

Способ первый: посколькуjava.util.HashMap имеет конструкторHashMap(Map<? extends K,? extends V> m)Вы можете передать ему действительную карту Java. И вы можете сделать это тривиально с помощью ScalaJavaConversions:

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, возможно), и что вы должны указать типы. Но это компактно и безболезненно.

Способ второй: Кроме того, вы можете создать новый блок кода в качестве оператора объявления, так что вам даже не нужно иметь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}

Чуть менее компактный, но полностью общий, и настолько эффективный (или неэффективный), насколько вы хотите это сделать.

Метод третий: Кроме того, вы можете создать анонимный подкласс HashMap до тех пор, пока подкласс будет нормально (т.е..getClass не вернется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.

Метод четвертый: И, наконец, конечно, вы можете создать метод, который делает то, что вы хотите, и вместо этого вызывать его:

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}

Это чуть менее компактно, чем у других, и дает правильные типы без необходимости их указания, так что это может быть привлекательным выбором, если вы делаете это более одного раза.

Постскриптум Просто для забавы я показал множество способов добавления некоторых пар ключ-значение на карту, но они не относятся к конкретному методу (за исключением # 1, для которого требуется карта). Смешивать и сочетать по своему вкусу.

 eggonlegs31 мар. 2013 г., 08:28
Это отличный ответ.

Ваш ответ на вопрос