添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Learn more about Collectives

Teams

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Learn more about Teams

I'm currently porting a program written in Python to Java and have run into some problems. I'm porting a part of the program at the time and for testing purposes I'm using JPype to make it compatible with the new java classes.

EDIT: Just to makes things more clear, the class I'm currently working on provides data to the rest of the Python program.

So, in my java class I have some float and byte values in ArrayLists,

    ArrayList<ArrayList<Float>> dataFloat  = new ArrayList<ArrayList<Float>>();
    ArrayList<ArrayList<Byte>>  dataByte   = new ArrayList<ArrayList<Byte>>();

Then with the use of JPype I am able to get these into my Python environment which now has the type

    <class 'jpype._jclass.java.util.ArrayList'> .

Now I wanted to simply convert these to numpy arrays in Python,

    numpy.array(dataFloat) .

Which seemed to work at first as it looked nice when it was printed out,

    [[1.0 2.0 3.0]
    [80.0 127.0 127.0]
    [255.0 255.0 255.0]] .

However, it did not work with the rest of the program because it demands that the values are of the type float. Looking further into the problem I found that these "float" values that I have are in fact

    <class 'jpype._jclass.java.lang.Float'>

and not the regular Python float that I wanted. Compared to a regular numpy float array,

>>> b = array([[1.1, 2.1, 3.1], [4.1, 5.1, 6.1], [7.1, 8.1, 9.1]])
>>> type((b[0])[0])
<type 'numpy.float64'>

which has the desired float type.

To be able to run it with the rest of the Python program I had to convert the array per element with the java Float.floatValue(),

    arr = numpy.array(dataFloat)
    a = array([])
    for j in range(len(arr)):
        b = array([])
        if array_equal(a,[]):
           for i in arr.get(j):
              a = append(a, i.floatValue())
        else:
           for i in arr.get(j):
              b = append(b, i.floatValue())
           a = vstack((a, b))   

And this of course takes a lot of time, especially when there are thousands of elements.

Does anyone know this can be done in an efficient way? Simply put, I get a lot java.lang.Float values from JPype that need to be converted to regular Python float values.

Could you not keep the program as is and fire up a jython interpreter inside the java code? – Jakob Bowyer Jun 30, 2011 at 9:55 For starters I don't have the slightest clue how to use jython, and not really sure what it provides. Thought JPype was nice since then I can call and use my Java-classes. This way I don't have to make any special modifications to my Java code to be able to test, just some rewriting in the Python code. Only issue I have had so far is this. Lets just say I would like to keep using JPype and not mess around with other Java<->Python packages :) – Mattias Jun 30, 2011 at 10:08 Basically jython is python written on the jvm. You can initializate a jython interpreter inside your java and then feed it python (basically) – Jakob Bowyer Jun 30, 2011 at 10:11 Ah okey, well the class I'm dealing with now provides information to the rest of the Python program and not the other way around. So in that case jython would not be of any help? – Mattias Jun 30, 2011 at 10:14 Jython works both ways, but it will not help in this case, as Numpy is partly implemented in C, and Jython can't deal with those librairies. – Daniel Teply Jul 4, 2011 at 14:12

I tried JPype some time ago and had some issues with type conversions too. Maybe you can speedup your code using http://cython.org/, there are some methods to speed up access to numpy data structures: http://docs.cython.org/src/tutorial/numpy.html

One further comment: vstack and hstack can copy with arbitrary lists/tuples. So you could rewrite your code like (untested)

arr = numpy.array(dataFloat)
a = []
for j in range(len(arr)):
    b = array([])
    for i in arr.get(j):
          b = append(b, i.floatValue())
    a.append(b)
a = vstack(a)   

Further you could optimise speed if you avoid the calls to append(). It is faster to allocate your array b with a fixed size N, eg using zero(), and then filling in the values:

arr = numpy.array(dataFloat)
N = ....
a = []
for j in range(len(arr)):
    b = zeros((N,))
    for k in range(N):
          i =arr.get(j)[k]:
          b[k] = i.floatValue()
    a.append(b)
a = vstack(a)   

Which only works if you know N.

Thanks for contributing an answer to Stack Overflow!

  • Please be sure to answer the question. Provide details and share your research!

But avoid

  • Asking for help, clarification, or responding to other answers.
  • Making statements based on opinion; back them up with references or personal experience.

To learn more, see our tips on writing great answers.