From: Updike, C. <Cla...@jh...> - 2003-12-20 15:21:01
|
I created a class that exposes a public Map field that stays sync'd with the underlying jython dictionary. You can instantiate is using either a dictionary or a map. Here's the code and an example demonstrating it in jython below. I keep meaning to try the same thing for a list but haven't gotten around to it. -Clark --------------------------------------------------------------------- import java.util.Collections; import java.util.HashMap; import java.util.Hashtable; import java.util.Iterator; import java.util.Map; import org.python.core.Py; import org.python.core.PyDictionary; import org.python.core.PyList; import org.python.core.PyTuple; /** * Exposes an unmodifiable java.util.Map as a public field * directly accessible from Jython. The map reflects * changes made through the PyDictionary methods. * * @see java.util.Map * @author clark */ public class PyJavaDictionary extends PyDictionary { /** The underlying dictionary PyDictionary exposed as an * unmodifyable Map. */ public final Map map; /** Initializes to the values contained in <code>aMap</code>. */ public PyJavaDictionary(Map aMap) { Map tmpMap = new HashMap(); Iterator it = aMap.entrySet().iterator(); while(it.hasNext()) { Map.Entry e = (Map.Entry)it.next(); tmpMap.put(Py.java2py(e.getKey()), Py.java2py(e.getValue())); } table = new Hashtable(tmpMap); map = Collections.unmodifiableMap(table); } /** Initializes to the values contained in <code>dict</code>. * Use this to construct from a native jython dictionary. */ public PyJavaDictionary(PyDictionary dict) { PyList list = dict.items(); table = new Hashtable(); for(int i = list.__len__(); i-- > 0; ) { PyTuple tup = (PyTuple)list.__getitem__(i); table.put(tup.__getitem__(0), tup.__getitem__(1)); } map = Collections.unmodifiableMap(table); } } --------------------------------------------------------------------- Jython 2.1 on java1.3.1_01 (JIT: null) Type "copyright", "credits" or "license" for more information. >>> import PyJavaDictionary as PJD >>> d = {'a':1, 'b':2, 'c':3} >>> >>> # create from a Jython Dictionary >>> pjd=PJD(d) >>> pjd {'b': 2, 'a': 1, 'c': 3} >>> pjd.keys() ['b', 'a', 'c'] >>> pjd.values() [2, 1, 3] >>> pjd['x']=25 >>> pjd {'x': 25, 'b': 2, 'a': 1, 'c': 3} >>> pjd.map {x=25, b=2, a=1, c=3} >>> >>> # are they still in synch? >>> pjd == PJD(pjd.map) and "YES" or "NO" 'YES' >>> >>> # but don't try to modify the map field! >>> pjd.map.put('y',25) Traceback (innermost last): File "<console>", line 1, in ? java.lang.UnsupportedOperationException at java.util.Collections$UnmodifiableMap.put(Collections.java:817) at java.lang.reflect.Method.invoke(Native Method) <snip> >>> pjd.map.keySet() [x, b, a, c] >>> >>> # create from a Map instance (just reuse the one from pjd) >>> pjd2=PJD(pjd.map) >>> pjd2 {'x': 25, 'b': 2, 'a': 1, 'c': 3} >>> >>> pjd2['y']=25 >>> pjd2 {'x': 25, 'b': 2, 'a': 1, 'y': 25, 'c': 3} >>> >>> pjd2.map {x=25, b=2, a=1, y=25, c=3} >>> >>> # are they still in synch? >>> PJD(pjd2.map)==pjd2 and "YES" or "NO" 'YES' --------------------------------------------------------------------- -----Original Message----- From: Si Chen Sent: Friday, December 19, 2003 6:19 PM To: jyt...@li... Subject: [Jython-users] Jython pyDictionary to Java HashMap conversion Hello. I have to return a java.util.Hashmap from my jython code, and I just realized that it is not an automatic conversion. For example, >>> pyMap = {"a":1,"b":2,"c":3} >>> pyMap.__class__ <jclass org.python.core.Pydictionary at ....> >>> from java.util import Hashmap >>> jMap = HashMap(pyMap) TypeError: java.util.HashMap(): 1st arg can't be coerced into int or java.util.Map I have not tried lists or arrays. Is there a way to automatically convert these back to java equivalents, or must I use the Java constructors and write Java code to have them properly returned as Java classes? Thanks in advance, Si Chen |