For 4 or fewer elements, something like this works (or at least compiles):
import scala.collection.immutable.Map;
Map<String,String> HAI_MAP = new Map4<>("Hello", "World",
"Happy", "Birthday",
"Merry", "XMas",
"Bye", "For Now");
For a 5th element I could do this:
Map<String,String> b = HAI_MAP.$plus(new Tuple2<>("Later", "Aligator"));
But I want to know how to initialize an immutable map with 5 or more elements and I’m flailing in Type-hell.
Partial Solution
I thought I’d figure this out quickly by compiling what I wanted in Scala, then decompiling the resultant class files. Here’s the scala:
object JavaMapTest {
def main(args: Array[String]) = {
val HAI_MAP = Map(("Hello", "World"),
("Happy", "Birthday"),
("Merry", "XMas"),
("Bye", "For Now"),
("Later", "Aligator"))
println("My map is: " + HAI_MAP)
}
}
But the decompiler gave me something that has two periods in a row and thus won’t compile (I don’t think this is valid Java):
scala.collection.immutable.Map HAI_MAP =
(scala.collection.immutable.Map)
scala.Predef..MODULE$.Map().apply(scala.Predef..MODULE$.wrapRefArray(
scala.Predef.wrapRefArray(
(Object[])new Tuple2[] {
new Tuple2("Hello", "World"),
new Tuple2("Happy", "Birthday"),
new Tuple2("Merry", "XMas"),
new Tuple2("Bye", "For Now"),
new Tuple2("Later", "Aligator") }));
I’m really baffled by the two periods in this:
scala.Predef..MODULE$
I asked about it on #java
on Freenode and they said the ..
looked like a decompiler bug. It doesn’t seem to want to compile, so I think they are probably right. I’m running into it when I try to browse interfaces in IntelliJ and am just generally lost.
Based on my experimentation, the following is valid:
Tuple2[] x = new Tuple2[] { new Tuple2<String,String>("Hello", "World"),
new Tuple2<String,String>("Happy", "Birthday"),
new Tuple2<String,String>("Merry", "XMas"),
new Tuple2<String,String>("Bye", "For Now"),
new Tuple2<String,String>("Later", "Aligator") };
scala.collection.mutable.WrappedArray<Tuple2> y = scala.Predef.wrapRefArray(x);
There is even a WrappedArray.toMap()
method but the types of the signature are complicated and I’m running into the double-period problem there too when I try to research the interfaces from Java.
4
The decompiler probably has problems in decompiling class names correctly that contain a $
symbol. The symbol you are searching for is named Predef$
:
import scala.Predef;
import scala.Predef$;
import scala.Tuple2;
import scala.collection.immutable.Map;
import scala.collection.mutable.WrappedArray;
public class T {
@SuppressWarnings({ "rawtypes", "unchecked" })
public static void main(final String... args) {
final Tuple2[] ts = { new Tuple2("a", "b") };
final WrappedArray wa = Predef.wrapRefArray(ts);
final Map<String, String> map = Predef$.MODULE$.Map().apply(wa);
System.out.println(map);
}
}
Thus, I emphasize not to use a decompiler but the internal representation of the AST in scalac:
$ scala -print -e 'Map(("a", "b"))'
...
scala.this.Predef.Map().apply(
scala.this.Predef.wrapRefArray(
Array[Tuple2]{new Tuple2("a", "b")}.$asInstanceOf[Array[Object]]()));
...
If you are interested in more information about how to work with the output of scalac then take a look at this question and its answers.
How about this?
java.util.Map<String, String> javaMap = new java.util.HashMap<String, String>();
javaMap.put("Hello", "World");
javaMap.put("Happy", "Birthday");
javaMap.put("Merry", "XMas");
javaMap.put("Bye", "For Now");
javaMap.put("Later", "Aligator");
scala.collection.Map<String, String> scalaMap = scala.collection.JavaConversions$.MODULE$.asMap(javaMap);
System.out.println(scalaMap);
1