通过JPype和numpy将Java类型转换为Python
我现在正在把一个用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 个回答
我之前试过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的时候才有效。