Я вижу некоторое нечетное поведение в javax.scripting реализации Map.
Примеры онлайн показывают пример добавления к списку в js среде:
ScriptEngineManager mgr = new ScriptEngineManager();
ScriptEngine jsEngine = mgr.getEngineByName("JavaScript");
List namesList = new ArrayList();
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);
Однако, при попытке сделать что-то похожее с картой, Вы видите нечетное поведение. С одной стороны, при попытке выполнить итерации через ключи карты, например.
HashMap m = new HashMap();
jsEngine.put("map", m);
Нет никакого способа получить ключи карты - при попытке выполнить итерации через ключи, Вы получаете имена методов -
jsEngine.eval(" for (var k in m.keySet()){ println(k)};");
результаты в:
notifyAll
removeAll
containsAll
contains
empty
equals
...
В js контексте можно обратиться к значениям в карте с m.get(key)
но не с m[key]
, и если ключ не существует, он бросает ошибку. Кто-либо может пролить некоторый свет на это поведение, или это просто повреждается?Спасибо.
for..in в JavaScript - это не то же самое, что for..each в Java, даже если они выглядят одинаково. for..in в JavaScript выполняет итерацию по именам свойств в объекте. Имена методов предоставляются Rhino как свойства в собственном объекте Java HashMap, как если бы у вас был следующий объект JavaScript:
{
notifyAll:function(){},
removeAll:function(){},
containsAll:function(){},
contains:function(){},
empty:function(){},
equals:function(){}
}
Я рекомендую вам либо преобразовать набор ключей HashMap в массив, используя метод Set.toArray, либо вы получаете итератор, используя 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);
}
Какие результаты:
bif
bar
boo
Вот как вы можете сделать то же самое с помощью 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);
}