Импорт карты в javax.scripting среде JavaScript

Я вижу некоторое нечетное поведение в 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], и если ключ не существует, он бросает ошибку. Кто-либо может пролить некоторый свет на это поведение, или это просто повреждается?Спасибо.

10
задан Teja Kantamneni 13 August 2010 в 17:21
поделиться

1 ответ

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);
}
13
ответ дан 3 December 2019 в 22:34
поделиться
Другие вопросы по тегам:

Похожие вопросы: