Transform a Generic Array Efficiently Using Guava

给你一囗甜甜゛ 提交于 2020-01-03 17:59:50

问题


I'm working with Java 7, and I'm searching in the Guava API for a way to apply a function to an array without having to convert it to a Collection first. I'm willing to create my own class for such purpose, but I don't want to reinvent the wheel hehe.

So as a summary (in case you don't know exactly what I'm talking about), this is what I've found so far that you can do with Guava in order to apply a function to an array as I said:

Integer[] someNumbers = new Integer[]{1, 2, 3};
Integer[] returnedNumbers = Collections2.transform(Arrays.asList(someNumbers), squareNumberFunction).toArray(new Integer[0]);

assertThat(returnedNumbers).isEqualTo(new Integer[]{1, 4, 9});//Using AssertJ here

But I would like to be able to do something like this instead:

Integer[] someNumbers = new Integer[]{1, 2, 3};
Integer[] returnedNumbers = Arrays.transform(someNumbers, squareNumberFunction);

assertThat(returnedNumbers).isEqualTo(new Integer[]{1, 4, 9});

Ideally the functionality I'm talking about would be type-safe.


EDIT

For even further clarification of the problem:

  • The arrays I'm talking about are not primitive arrays, they reference complex objects (I only used integers to easily exemplify what I was talking about).
  • I have no control over the received or send structures, they are arrays (imagine a legacy code situation where that's possible if you think that helps you understand the problem better).
  • Efficiency is a must when transforming the arrays and accessing them.

回答1:


It's not true that arrays are considerably faster than collections - some collections are just wrappers over arrays so you loose nothing but gets the best of both worlds.

Coming back to your case I think you can use Arrays.asList (a list backed by your array) or ImmutableList (if you don't need growing array) whatever suits you but don't use Arrays. The very first sign is that you have to write unnecessary code (your answer and more in future) which you'll have to maintain/tune in future, in my experience it's not worth it.

Java is a higher level language and such tiny optimizations should be better left to Java for all the good reasons but even after all this if you still have doubts I would suggest you to write a micro benchmark to validate your assumption.




回答2:


Okay, I ended up writing my own code in order to solve the aforementioned problem. So I hope someone else find it useful too, and don't just have to resort to using collections (come on, why would you have to?).

public static <A, B> B[] transform(Class<B> theReturnedValueType, Function<A, B> functionToApply, A... theValues) {

    B[] transformedValues = (B[]) Array.newInstance(theReturnedValueType, theValues.length);

    for (int i = 0; i < theValues.length; i++) {
        transformedValues[i] = functionToApply.apply(theValues[i]);
    }

    return transformedValues;
}

Example of how to use it (actually this is a test):

Integer[] returnedNumbers = ArrayTransformer.transform(Integer.class, squareNumberFunction, 1, 2, 3);

assertThat(returnedNumbers).isEqualTo(new Integer[]{1, 4, 9});

I want to point out that the example code is using vargargs syntax (it's a test, so it's a fun way to use it) but you can just obviously passed an array object instead.

Also, I must add that you need to be careful with this approach when using it on an environment sensitive to reflection performance hits (such as Android), because of the runtime creation of the new array using reflection (java.lang.reflect.newInstance(...)). In the other hand, the same holds true if you are using toArray(T[]) method of collections and the passed array's size isn't enough to hold all the collection elements (in which case a new array is allocated at run time, just as with my code), so maybe this code doesn't represent a problem if anyway you are using that method in the way I said (in any case you could easily change this code to fit your needs).



来源:https://stackoverflow.com/questions/27087881/transform-a-generic-array-efficiently-using-guava

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!