How do I convert Double[] to double[]?
Asked Answered
B

8

74

I'm implementing an interface that has functionality similar to a table that can contain an types of objects. The interface specifies the following function:

double[] getDoubles(int columnIndex);

Where I'm stumped is that in my implementation, I'm storing the table data in a 2D Object array (Object[][] data). When I need to return the values, I want to do the following (it is assumed that getDoubles() will only be called on a column that contains doubles, so there will be no ClassCastExceptions):

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

But - Java doesn't allow Object[] to be cast to double[]. Casting it to Double[] is ok because Double is an object and not a primitive, but my interface specifies that data will be returned as a double[].

So I have two questions:

  1. Is there any way I can get the column data out of the Object[][] table and return the array of primitives?
  2. If I do change the interface to return Double[], will there be any performance impact?
Been answered 10/7, 2009 at 14:46 Comment(4)
Why do you need to have data as Object[][]?Osy
The table can store any type of data: strings, doubles, integers, other types, etc.Been
Then how can you insure that array at the columnIndex contains only Doubles/doubles?Osy
Anyone using the interface is responsible for only calling getDoubles() on a column that contains doubles.Been
A
34

Unfortunately you will need to loop through the entire list and unbox the Double if you want to convert it to a double[].

As far as performance goes, there is some time associated with boxing and unboxing primitives in Java. If the set is small enough, you won't see any performance issues.

Athenaathenaeum answered 10/7, 2009 at 14:52 Comment(2)
Although not directly applicable, tests in C# on sorting large (one million elements) arrays with primitive vs boxed types showed the primitive sort to be 3 times as fast. I mention this because it illustrates the auto-boxing/unboxing cost can be significant.Ayannaaycock
Wow. That is way more significant than I would have expected. I would not consider 1 million a small set though.Athenaathenaeum
W
96

If you don't mind using a 3rd party library, commons-lang has the ArrayUtils type with various methods for manipulation.

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

There is also the complementary method

doubles = ArrayUtils.toObject(d);

Edit: To answer the rest of the question. There will be some overhead to doing this, but unless the array is really big you shouldn't worry about it. Test it first to see if it is a problem before refactoring.

Implementing the method you had actually asked about would give something like this.

double[] getDoubles(int columnIndex) {
    return ArrayUtils.toPrimitive(data[columnIndex]);
}
Wildawildcat answered 10/7, 2009 at 15:9 Comment(4)
Thanks for the info that commons-lang has that functionality, it'll be very useful in the future if I decide to go with any 3rd party librariesBeen
I prefer this to the answer of looping through. Its much better to use a third-party API for boilerplate code such as thisMattins
using third-party libs may look good (after all, a one-liner code looks so much better than an ugly for loop...) but the implementation is no different than a manual Double-to-double conversion. Worst! There is even a ternary operator for each iterations witch may result in even more computer processing. My point is that "preferring" a solution should consider performance and usefulness over code aesthetics. :) my 2c.Hexahydrate
As a compromise, you could hide your ugly code in a static Utils class, with a couple of unit tests, just to make sure you can rely on it. This way you're code looks great, and you didn't need to worry about performance or depending on a third party library.Petepetechia
H
59

In Java 8, this is one-liner:

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

Note that this still iterates over the original array and creates a new one.

Heptane answered 8/5, 2015 at 6:55 Comment(1)
This is what I was looking for !Whelk
A
34

Unfortunately you will need to loop through the entire list and unbox the Double if you want to convert it to a double[].

As far as performance goes, there is some time associated with boxing and unboxing primitives in Java. If the set is small enough, you won't see any performance issues.

Athenaathenaeum answered 10/7, 2009 at 14:52 Comment(2)
Although not directly applicable, tests in C# on sorting large (one million elements) arrays with primitive vs boxed types showed the primitive sort to be 3 times as fast. I mention this because it illustrates the auto-boxing/unboxing cost can be significant.Ayannaaycock
Wow. That is way more significant than I would have expected. I would not consider 1 million a small set though.Athenaathenaeum
I
8

You could use a for each loop to construct a temp array of the same size then cast each individual element to double and but it in the array.

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

Please correct me if I am dead wrong here.

Insignificance answered 10/7, 2009 at 14:54 Comment(3)
This one is actually simpler solution than the othersLopeared
@Lopeared If by simpler, you mean lacking FOP constructs and third party dependencies, then yes. But if you have either of those things available to you then I would argue that this is way more code than necessary.Alabaster
Did no-one in the last 15 years notice that this doesn’t work? for(Double d : (Double) data[columnIndex]) should be for(Double d : (Double[]) data[columnIndex])Broglie
O
3

If you wanted to return a double[], you would need to create a new double[], populate it, and return that.

That may be a good architecture decision. First, it doesn't make a lot of sense to cast an Object[] to a Double[]; it's not really an array of Double because there could be Objects in it too. Second, if you return the array directly, the user code can modify it and alter the internal structure of your object.

The main performance impact would be in returning an array of double[], due to unboxing and the cost of allocation.

Opposite answered 10/7, 2009 at 14:53 Comment(0)
O
3

You can utilise the ArrayUtils to convert

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

No need of looping the entire data.

Overheat answered 15/2, 2017 at 13:28 Comment(0)
E
1

I don't have anything to add to the real question beyond what jjnguy and Eric Koslow said.

But just a side note: You mention casting an Object array to a Double array. The following will NOT work:

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;

The last line will throw a class cast exception. Even though every element in the array is indeed a Double, the array was created as an array of Objects, not an array of Doubles, so the cast is invalid.

Epagoge answered 10/7, 2009 at 16:56 Comment(0)
D
0

I would second the ArrayUtils answer and add that the 1.5 autoboxing documentation(via) kinda reveals that there is no builtin way:

There is no permitted conversion from array type SC[] to array type TC[] if there is no permitted conversion other than a string conversion from SC to TC

Displeasure answered 10/7, 2009 at 16:33 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.