GroovyのLongとInteger

Groovy で、partition by parity を解いている時に、またちょっと、うざい挙動にぶちあたった。

m="10 11 12".split()*.toLong().groupBy{it%2}
println"$m"                    //-> [0:[10, 12], 1:[11]]
println"${m[0]}"               //-> null
println"${m[1]}"               //-> null

となる。なんで、null なの?しばらく悩んだ。
答えは、

println"${m[0L]}"              //-> [10, 12]
println"${m[1L]}"              //-> [11]

ということ。つまり、マップの key が Integer オブジェクトではなく、Long オブジェクトになっているためだ。int と long の計算を行うときは、long にプロモートされるということがあるが、ここでは、そういった動きは無い。単にタイプの異なるオブジェクトが key になっているということらしい。
なお、これは、Groovy ではなく、Java の挙動だった。

public static void main(String[]a){
    Map m=new HashMap();
    m.put(0L, 500);
    System.out.println(m.get(0));     //-> (nothing)
    System.out.println(m.get(0L));    //-> 500
}

しかも、

public static void main(String[]a){
    Map<Long,Long>m=new HashMap<Long,Long>();
    m.put(0, 500);                   //-> Syntax Error
    m.put(0L, 500L);                 //-> OK
}

だ。オブジェクト間にプロモーションという考えはありえないのか?まぁ、long と Long があるところですでに気持ちよくはないな。因みに、

[1:10, 1L:20, 1g:30, (1 as short):40]   //-> [1:10, 1:20, 1:30, 1:40]

となる。そのくせ、

[1, 1L, 1g, 1 as short].unique()        //-> [1]

となる。