Как конвертировать Double [] в double []? - PullRequest
62 голосов
/ 10 июля 2009

Я реализую интерфейс с функциональностью, аналогичной таблице, которая может содержать типы объектов. Интерфейс определяет следующую функцию:

double[] getDoubles(int columnIndex);

Где я озадачен тем, что в моей реализации я храню данные таблицы в массиве 2D Object (Object[][] data). Когда мне нужно вернуть значения, я хочу сделать следующее (предполагается, что getDoubles() будет вызываться только для столбца, который содержит двойные значения, поэтому ClassCastExceptions не будет):

double[] getDoubles(int columnIndex) {
    return (double[]) data[columnIndex];
}

Но - Java не позволяет Object[] быть приведенным к double[]. Преобразование в Double[] нормально, поскольку Double является объектом, а не примитивом, но мой интерфейс указывает, что данные будут возвращены как double[].

Итак, у меня два вопроса:

  1. Можно ли как-нибудь получить данные столбца из таблицы Object[][] и вернуть массив примитивов?
  2. Если я изменю интерфейс для возврата Double[], будет ли какое-либо влияние на производительность?

Ответы [ 8 ]

85 голосов
/ 10 июля 2009

Если вы не возражаете против использования сторонней библиотеки, commons-lang имеет тип ArrayUtils с различными методами для манипуляции.

Double[] doubles;
...
double[] d = ArrayUtils.toPrimitive(doubles);

Существует также дополнительный метод

doubles = ArrayUtils.toObject(d);

Редактировать: чтобы ответить на остальную часть вопроса. Это потребует некоторых дополнительных затрат, но если массив не очень большой, вам не стоит об этом беспокоиться. Сначала проверьте его, чтобы убедиться, что это проблема перед рефакторингом.

Реализация метода, о котором вы на самом деле спрашивали, дала бы что-то вроде этого.

double[] getDoubles(int columnIndex) {
    return ArrayUtils.toPrimitive(data[columnIndex]);
}
46 голосов
/ 08 мая 2015

В Java 8 это одна строка:

Double[] boxed = new Double[] { 1.0, 2.0, 3.0 };
double[] unboxed = Stream.of(boxed).mapToDouble(Double::doubleValue).toArray();

Обратите внимание, что он по-прежнему перебирает исходный массив и создает новый.

33 голосов
/ 10 июля 2009

К сожалению, вам нужно будет перебрать весь список и распаковать Double, если вы хотите преобразовать его в double[].

Что касается производительности, то в Java есть время, связанное с примитивами упаковки и распаковки. Если набор достаточно мал, проблем с производительностью не будет.

7 голосов
/ 10 июля 2009

Вы можете использовать a для каждого цикла для создания временного массива одинакового размера, а затем приводить каждый отдельный элемент к удвоению, но только в массиве.

SO:

double[] tempArray = new double[data[columnIndex].length];
int i = 0;
for(Double d : (Double) data[columnIndex]) {
  tempArray[i] = (double) d;
  i++;
}

Пожалуйста, поправьте меня, если я здесь неправ.

3 голосов
/ 10 июля 2009

Если вы хотите вернуть double[], вам нужно создать new double[], заполнить его и вернуть.

Это может быть хорошим архитектурным решением. Во-первых, не имеет смысла разыгрывать Object[] до Double[]; это не совсем массив Double, потому что в нем тоже может быть Object s. Во-вторых, если вы возвращаете массив напрямую, код пользователя может изменить его и изменить внутреннюю структуру вашего объекта.

Основным воздействием на производительность будет возвращение массива double[] из-за распаковки и стоимости размещения.

1 голос
/ 10 июля 2009

Мне нечего добавить к реальному вопросу, кроме того, что сказали jjnguy и Эрик Козлов.

Но только примечание: вы упоминаете приведение массива Object к массиву Double. Следующее НЕ будет работать:

Object[] oa=new Object[3];
oa[0]=new Double("1.0");
oa[1]=new Double("2.0");
oa[2]=new Double("3.0");
Double[] da=(Double[])oa;

Последняя строка выдаст исключение приведения класса. Несмотря на то, что каждый элемент в массиве действительно является Double, массив был создан как массив объектов, а не как массив Double, поэтому приведение является недействительным.

0 голосов
/ 15 февраля 2017

Вы можете использовать ArrayUtils для преобразования

Double[] d; // initialise
double[] array = ArrayUtils.toPrimitive(d);

Нет необходимости зацикливать все данные.

0 голосов
/ 10 июля 2009

Я бы добавил ответ ArrayUtils и добавил, что документация по автоматическому боксу 1.5 ( через ) вроде показывает, что встроенного пути нет:

Нет разрешенного преобразования из типа массива SC [] в тип массива TC [], если нет разрешенного преобразование, кроме преобразования строки из SC в TC

...