2009-07-10 8 views
54

Я реализую интерфейс, который имеет функциональность, похожую на таблицу, которая может содержать типы объектов. Интерфейс определяет следующие функции:Как преобразовать Double [] в double []?

double[] getDoubles(int columnIndex); 

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

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

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

Поэтому у меня есть два вопроса:

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

Зачем вам нужны данные как Object [] []? – notnoop

+0

В таблице могут храниться данные любого типа: строки, двойники, целые числа, другие типы и т. Д. – Brian

+0

Тогда как вы можете обеспечить, чтобы массив в столбцеIndex содержал только парные/двойные числа? – notnoop

ответ

31

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

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

+4

Несмотря на то, что тесты на C# при сортировке больших (миллионных элементов) массивов с примитивными и коробочными типами не показали, что примитивный сорт был в 3 раза быстрее. Я упоминаю об этом, потому что он иллюстрирует, что стоимость автоматического бокса/распаковки может быть значительной. – cletus

+0

Ничего себе. Это гораздо более значительным, чем я ожидал. Хотя я бы не стал рассматривать 1 миллион небольшой набор. – jjnguy

3

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

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

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

7

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

SO:

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

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

+0

Это на самом деле более простое решение, чем другие. – Ryde

76

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

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

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

doubles = ArrayUtils.toObject(d); 

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

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

double[] getDoubles(int columnIndex) { 
    return ArrayUtils.toPrimitive(data[columnIndex]); 
} 
+0

Спасибо за информацию, что commons-lang имеет эту функциональность, это будет очень полезно в будущем, если я решит пойти с любыми сторонними библиотеками. – Brian

+0

Я предпочитаю это ответить зацикливание. Его гораздо лучше использовать сторонний API для шаблона кода, такой как этот – Richard

+5

, используя сторонние библиотеки, может показаться хорошим (в конце концов, один-линейный код выглядит намного лучше, чем уродливый цикл цикла ...), но реализация ничем не отличается от ручного преобразования Double-to-double. Наихудший!Существует даже тройной оператор для каждой итерации, что может привести к еще большей компьютерной обработке. Я хочу сказать, что «предпочтение» решения должно учитывать производительность и полезность над эстетикой кода. :) мой 2c. –

0

Я бы второй в ArrayUtils ответить и добавить, что 1,5 autoboxing documentation (via) своего рода показывает, что нет встроенной способ:

Там не допускается преобразование типа массива SC [] в массив типа TC [], если не допускается преобразования, кроме преобразования строки из SC в TC

1

у меня нет ничего, чтобы добавить к реальному вопросу за то, что jjnguy и Eric K сказал oslow.

Но только примечание стороны: вы указываете, что для массива объектов используется массив объектов. Следующие действия НЕ будут работать:

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; 

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

32

В Java 8, это один вкладыш:

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

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

+0

Это то, что я искал! –

1

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

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

Нет необходимости в перекручивание все данные.

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