在javax.scripting javascript环境中导入地图

Ste*_* B. 10 java rhino

我在javax.scripting地图实现中看到了一些奇怪的行为.

在线示例显示了在js环境中添加到列表的示例:

ScriptEngineManager mgr = new ScriptEngineManager();
  ScriptEngine jsEngine = mgr.getEngineByName("JavaScript");
  List<String> namesList = new ArrayList<String>();
  namesList.add("Jill");
  namesList.add("Bob");
  namesList.add("Laureen");
  namesList.add("Ed");
  jsEngine.put("namesListKey", namesList);
  System.out.println("Executing in script environment...");
  try
  {
   jsEngine.eval("var names = namesListKey.toArray();" + "for(x in names) {" + "  println(names[x]);" + "}"
     + "namesListKey.add(\"Dana\");");
  } catch (ScriptException ex)
  {
   ex.printStackTrace();
  }
  System.out.println(namesList);
Run Code Online (Sandbox Code Playgroud)

但是,如果您尝试使用地图执行类似操作,则会看到奇怪的行为.首先,如果您尝试迭代地图键,例如

 HashMap<String, Object> m = new HashMap<String, Object>();
 jsEngine.put("map", m);
Run Code Online (Sandbox Code Playgroud)

无法获取地图密钥 - 如果您尝试迭代密钥,则会获得方法名称 -

jsEngine.eval(" for (var k in m.keySet()){ println(k)};");
Run Code Online (Sandbox Code Playgroud)

结果是 :

notifyAll
removeAll
containsAll
contains
empty
equals
...
Run Code Online (Sandbox Code Playgroud)

在js上下文中,您可以使用m.get(key)但不使用地址来映射映射中的值m[key],如果该键不存在,则会引发错误.任何人都可以对这种行为有所了解,还是只是打破了?谢谢.

jbe*_*rd4 13

JavaScript中的for..in与Java中的.each不同,即使它们看起来相似.for..in在JavaScript中迭代对象中的属性名称.方法名称作为本机Java HashMap对象的属性公开给Rhino,就像您有以下JavaScript对象一样:

{
notifyAll:function(){},
removeAll:function(){},
containsAll:function(){},
contains:function(){},
empty:function(){},
equals:function(){}
}
Run Code Online (Sandbox Code Playgroud)

我的建议是使用方法Set.toArray将HashMap键集转换为数组,或者使用Set.iterator()获取迭代器.这是一个简短的Rhino脚本,展示了如何使用toArray方法完成此任务:

x=new java.util.HashMap();
x.put("foo","bar");
x.put("bat","bif");
x.put("barf","boo");

var keyArray = x.keySet().toArray();
for(var i=0, l = keyArray.length; i < l; i++){
    var key = keyArray[i]; 
    var value = x.get(key);
    print(value);
}
Run Code Online (Sandbox Code Playgroud)

哪个输出:

bif
bar
boo
Run Code Online (Sandbox Code Playgroud)

以下是使用Set.iterator执行相同操作的方法:

x=new java.util.HashMap();
x.put("foo","bar");
x.put("bat","bif");
x.put("barf","boo");

var keyIter = x.keySet().iterator();
while(keyIter.hasNext()){
    var key = keyIter.next() 
    var value = x.get(key);
    print(value);
}
Run Code Online (Sandbox Code Playgroud)