简体   繁体   English

JNI - java ArrayList转换为c ++ std :: string *

[英]JNI - java ArrayList conversion to c++ std::string*

I am trying to make a data conversion with JNI in c++. 我试图用C ++中的JNI进行数据转换。 I have come into trouble working with java 's ArrayList of strings , since I have not been able to convert such a data into a c++ vector or std::string* . 我在使用java字符串 ArrayList时遇到了麻烦,因为我无法将这样的数据转换为c ++ 向量std :: string *

I would like to know how this conversion can be made without sacrificing too much performance, if possible. 我想知道如果可能的话,如何在不牺牲太多性能的情况下进行转换。 Any ideas would be appreciated. 任何想法,将不胜感激。

I don't know if this fits your performance requirements, but it may be a good start. 我不知道这是否符合您的性能要求,但它可能是一个良好的开端。

For both options assume that jobject jList; 对于这两个选项,假设jobject jList; is your ArrayList. 是你的ArrayList。

Option 1 选项1

Convert the List into an array and iterate on the array (maybe more applicable if you have a LinkedList instead of an ArrayList) 将List转换为数组并迭代数组(如果你有LinkedList而不是ArrayList,可能更适用)

// retrieve the java.util.List interface class
jclass cList = env->FindClass("java/util/List");

// retrieve the toArray method and invoke it
jmethodID mToArray = env->GetMethodID(cList, "toArray", "()[Ljava/lang/Object;");
if(mToArray == NULL)
    return -1;
jobjectArray array = (jobjectArray)env->CallObjectMethod(jList, mToArray);

// now create the string array
std::string* sArray = new std::string[env->GetArrayLength(array)];
for(int i=0;i<env->GetArrayLength(array);i++) {
    // retrieve the chars of the entry strings and assign them to the array!
    jstring strObj = (jstring)env->GetObjectArrayElement(array, i);
    const char * chr = env->GetStringUTFChars(strObj, NULL);
    sArray[i].append(chr);
    env->ReleaseStringUTFChars(strObj, chr);
}

// just print the array to std::cout
for(int i=0;i<env->GetArrayLength(array);i++) {
    std::cout << sArray[i] << std::endl;
}

Option 2 选项2

An alternative would be to use the List.size() and List.get(int) methods to retrieve the data from the list. 另一种方法是使用List.size()List.get(int)方法从列表中检索数据。 As you use an ArrayList this solution would also be okay as the ArrayList is an RandomAccessList. 当您使用ArrayList时,此解决方案也可以,因为ArrayList是RandomAccessList。

// retrieve the java.util.List interface class
jclass cList = env->FindClass("java/util/List");

// retrieve the size and the get method
jmethodID mSize = env->GetMethodID(cList, "size", "()I");
jmethodID mGet = env->GetMethodID(cList, "get", "(I)Ljava/lang/Object;");

if(mSize == NULL || mGet == NULL)
    return -1;

// get the size of the list
jint size = env->CallIntMethod(jList, mSize);
std::vector<std::string> sVector;

// walk through and fill the vector
for(jint i=0;i<size;i++) {
    jstring strObj = (jstring)env->CallObjectMethod(jList, mGet, i);
    const char * chr = env->GetStringUTFChars(strObj, NULL);
    sVector.push_back(chr);
    env->ReleaseStringUTFChars(strObj, chr);
}

// print the vector
for(int i=0;i<sVector.size();i++) {
    std::cout << sVector[i] << std::endl;
}

_edited: replaced JNI_FALSE with NULL_ _edited:用NULL_替换JNI_FALSE
_edited: replaced insert with push_back_ _edited:用push_back_替换插入

You could also use classic java iterators from within JNI, having the loop equally optimized both for ArrayList and LinkedList . 您还可以在JNI中使用经典的Java迭代器,同时为ArrayListLinkedList优化循环。

jobject jIterator = env->CallObjectMethod(jList, env->GetMethodID(env->GetObjectClass(jList), "iterator", "()Ljava/util/Iterator;"));
jmethodID nextMid = env->GetMethodID(env->GetObjectClass(jIterator), "next", "()Ljava/lang/Object;");
jmethodID hasNextMid = env->GetMethodID(env->GetObjectClass(jIterator), "hasNext", "()Z");

while (env->CallBooleanMethod(jIterator, hasNextMid)) {
    jobject jItem = env->CallObjectMethod(jIterator, nextMid);
    /* do something with jItem */
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM