通过JPype和numpy将Java类型转换为Python

6 投票
1 回答
3515 浏览
提问于 2025-04-16 20:35

我现在正在把一个用Python写的程序移植到Java上,遇到了一些问题。我是分部分移植程序的,为了测试,我使用JPype来让它和新的Java类兼容。

补充说明一下,我现在正在处理的这个类是给Python程序的其他部分提供数据的。

在我的Java类中,有一些浮点数和字节值存储在ArrayList里,

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

然后通过JPype,我能够把这些值带到我的Python环境中,现在这些值的类型是

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

我现在想把这些值简单地转换成Python中的numpy数组,

    numpy.array(dataFloat) .

起初看起来是可以的,因为打印出来的结果很好,

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

但是,它和程序的其他部分不兼容,因为程序要求这些值是浮点数类型。进一步调查后,我发现这些“浮点数”实际上是

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

而不是我想要的普通Python浮点数。与普通的numpy浮点数组相比,

>>> 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'>

后者才是我想要的浮点数类型。

为了能让它和Python程序的其他部分一起运行,我不得不逐个元素地用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))   

这当然非常耗时,尤其是当元素有成千上万的时候。

有没有人知道有没有更有效的方法?简单来说,我从JPype得到了很多java.lang.Float值,需要把它们转换成普通的Python浮点值。

1 个回答

0

我之前试过JPype,也遇到了一些类型转换的问题。也许你可以试试用http://cython.org/来加速你的代码,它有一些方法可以加快访问numpy数据结构的速度:http://docs.cython.org/src/tutorial/numpy.html

还有一点要提的是,vstack和hstack可以处理任意的列表或元组。所以你可以把你的代码改成这样(这个没测试过)

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)   

另外,如果你避免调用append(),可以进一步提高速度。你可以先用固定大小N来分配你的数组b,比如用zero(),然后再填入值:

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)   

这只有在你知道N的时候才有效。

撰写回答