如何从Java中调用Scala的HashMap.toArray()方法?

4
我在一些Java代码中使用了scala.collection.immutable.HashMap<A,B>,并希望使用Scala本地的toArray()方法来将map的内容(或值)转换为数组。

我目前使用JavaConversions.asMap()等方法,然后使用传统但丑陋的Java toArray(T[])方法,但我更愿意直接调用Scala内置的方法。

必须从Java中完成这个操作。重写Scala代码不是一个选项。

我正在使用Scala 2.9.1版本。

4个回答

2
你需要为数组类型 T 提供一个 ClassManifest。这可以从 ClassManifest 的伴生对象中获取(参见注释)。因此,代码如下:
itr.toArray(ClassManifest$.MODULE$.fromClass(T.class));

在这个例子中,T 是一个实际类型(而不是类型参数)。因此,例如,如果 itr 是一个 Seq [String],你会使用这个;
itr.toArray(ClassManifest$.MODULE$.fromClass(String.class));

由于Scala的Map实际上是一堆元组,因此您可以使用以下代码:
map.toArray(ClassManifest$.MODULE$.fromClass(Tuple2.class));

当然,这会给您一个Tuple2[],而不是Tuple2<K,V>[],其中KV分别表示键和值类型。由于您处于Java领域,您可以将其强制转换为原始类型。
注意:从Java访问伴生对象。
类型M的伴生对象可通过访问静态字段M$.MODULE$获得。

我认为ClassManifest$.MODULE$是在ClassManifest.scala中定义的ClassManifest对象。我担心它的文档,其中说“它是供编译器使用的,不应在客户端代码中使用。” - Per Mildner
关于“伴生对象”,它可能不适用于普通的Java类型(除非Scala比我想象的更强大)。在这种情况下,ClassManifest$.MODULE$.fromClass(SomeType.class)是否也适用于Scala类型(例如Tuple2,应该已经有预定义的Tuple2$.MODULE$)? - Per Mildner
使用(SomeType[])(...一些Scala集合).toArray(ClassManifest$.MODULE$.fromClass(SomeType.class))似乎效果不错。我唯一担心的是文档声称ClassManifest对客户端代码是禁止的。 - Per Mildner
实际上,理论上,Scala团队可以更改这个。但是,我怀疑他们不会这样做而没有征求社区反馈。还有一件事:不要忘记,在运行时,Scala只是一个JAR文件。仅仅因为发布了新版本的Scala并不强制您将其放在类路径上。 - oxbow_lakes
我以为对象应该有静态的转发方法,这样你就不需要整个 $.MODULE$ 的东西了……它们在这种情况下不起作用吗? - Luigi Plinge

1

这应该足够了:

map.toArray(scala.reflect.ClassManifest$.MODULE$.Object);

0
从API文档来看,似乎需要提供一个类型为Manifest(或ArrayTag,取决于版本)的参数给toArray函数。

0

从Java中调用Scala特定的方法有时可能会非常丑陋,就像在这种情况下一样。我不知道是否有更好的解决方案,但这应该可以解决:

import scala.collection.immutable.HashMap;

import scala.Tuple2;
import scala.reflect.ClassManifest$;
import scala.reflect.ClassManifest;

public class Foo {
  public static void main(String[] args) {
    HashMap<String,String> map = new HashMap();
    Object ar = map.<Tuple2<String,String>>toArray((ClassManifest<Tuple2<String,String>>)ClassManifest$.MODULE$.fromClass(new Tuple2<String,String>("","").getClass()));
    System.out.println(ar.toString());
  }
}

我不知道在Java中是否有一种方法可以在不实例化的情况下获取Class<Tuple2<String,String>>。在Scala中,我会使用classOf[...],那么在Java中是否有相应的方法呢?


.class应该以与classOf相同的方式获取类。 - Submonoid
好的,找到了一个不太优雅的解决方案 ;-). (Class<Tuple2<String,String>>)(Object)Tuple2.class 可以使用。 - drexin
只需删除类型参数。类型参数与“类”无关。 - Daniel C. Sobral
如果您想获得一个类型化的结果,这是相关的。 - drexin
@drexin - 但是类型不正确T<U>[]这样的东西根本不存在,代码也不应该表现得好像存在一样。 - oxbow_lakes

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接