2014-11-23 2 views
4

Я работаю с Java 7, и я ищу в API-интерфейсе Guava способ применения функции к массиву без необходимости сначала преобразовывать его в коллекцию. Я готов создать свой собственный класс для этой цели, но я не хочу изобретать колесо.Преобразование общего массива с использованием Guava

Так как резюме (если вы точно не знаете, о чем я говорю), это то, что я нашел до сих пор, что вы можете сделать с Guava, чтобы применить функцию к массиву как Я сказал:

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 

Но я хотел бы быть в состоянии сделать что-то вроде этого, вместо:

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

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

в идеале функциональность я говорю о будет типобезопасный.


EDIT

Для еще дальнейшего уточнения проблемы:

  • Массивы я говорю о не примитивные массивы, они ссылаются на сложные объекты (я использовал только целые числа для легко иллюстрировать то, о чем я говорил).
  • У меня нет контроля над не получило или отправить структуру, они являются массивов (представьте себе ситуацию, унаследованный код, где это возможно, если вы думаете, что поможет вам понять эту проблему лучше).
  • Эффективность является должна когда преобразования массивов и доступа их.
+4

Дженерики и массивы не сочетаются друг с другом. Почему вы используете массивы в первую очередь вместо списков? Это то, что вам следует делать: предпочитайте коллекции по массивам. –

+0

Да, к сожалению, проблема в том, что ** Мне нужно использовать массивы ** для этого случая, а также мне нужно ** эффективность ** при преобразовании массивов (может быть любого типа). –

+2

У вас будет более эффективная работа с использованием коллекций, поскольку она позволяет избежать копирования. Guava все о коллекциях, и AFAIK, вы не найдете метод, который вы хотите в Гуаве. Но ничто не запрещает вам писать обертку, содержащую код, опубликованный в вашем вопросе. –

ответ

4

Хорошо, я закончил тем, что написал свой собственный код, чтобы решить вышеупомянутую проблему. Поэтому я надеюсь, что кто-то найдет это полезным и не просто прибегает к использованию коллекций (давайте, зачем вам это нужно?).

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; 
} 

Пример того, как использовать его (на самом деле это тест):

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

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

Я хочу отметить, что пример кода использует vargargs синтаксис (это тест, так что это весело способ его использования), но вы можете просто явно передать объект массива.

Кроме того, я должен добавить, что вам нужно быть осторожным с этим подходом при использовании его в среде, чувствительной к ударам производительности отражения (например, Android), из-за создания времени создания нового массива с использованием отражения (java.lang .reflect.newInstance (...)). С другой стороны, то же самое верно, если вы используете метод toArray (T []) для коллекций, а размер переданного массива недостаточно для хранения всех элементов коллекции (в этом случае новый массив выделяется во время выполнения, так же, как и с моим кодом), поэтому, возможно, этот код не представляет проблемы, если в любом случае вы используете этот метод так, как я сказал (в любом случае вы можете легко изменить этот код в соответствии с вашими потребностями).

4

Неверно, что массивы значительно быстрее, чем коллекции - некоторые коллекции просто обертки над массивами, поэтому вы теряете ничего, но получаете best of both worlds.

Возвращаясь к вашему делу, я думаю, вы можете использовать Arrays.asList (список, поддерживаемый вашим массивом) или ImmutableList (если вам не нужен растущий массив), что вам подходит, но не использует массивы. Самым первым признаком является то, что вам нужно написать ненужный код (ваш ответ и многое другое в будущем), которое вам нужно будет поддерживать/настраивать в будущем, по моему опыту это не стоит.

Java - это язык более высокого уровня, и такие крошечные оптимизации должны быть лучше оставлены на Java по всем веским причинам, но даже после всего этого, если у вас все еще есть сомнения, я предлагаю вам написать микро-тест для подтверждения вашего предположения.

+0

Я никогда не говорил, что массивы значительно быстрее, чем коллекции (может быть, вы хотите процитировать меня?), Я только сказал, что ничто не может быть более эффективным, чем массив при определенных условиях. –

+0

С другой стороны, мне не нужна ** лучшая из двух миров ** для моей проблемы, потому что моя проблема ** живет ** только в одном мире ** (я добавил дополнительные разъяснения к своему сообщению, так что вы можете хочу проверить это). –

+0

Кроме того, я не планирую писать микро-бенчмарк, потому что я почти уверен, что ** ничто ** может бить итерирование массива и последовательно получать его элементы (много, много раз). –

Смежные вопросы