2009-07-10 46 views
54

Tôi đang triển khai giao diện có chức năng tương tự như bảng có thể chứa một loại đối tượng. Giao diện quy định cụ thể chức năng sau:Làm cách nào để chuyển đổi Double [] thành double []?

double[] getDoubles(int columnIndex); 

Nơi tôi đang bối rối là trong việc thực hiện của tôi, tôi lưu trữ các dữ liệu bảng trong một mảng 2D Object (Object[][] data). Khi tôi cần phải trả lại các giá trị, tôi muốn làm như sau (người ta cho rằng getDoubles() sẽ chỉ được gọi là trên một cột có chứa gấp đôi, vì vậy sẽ không có ClassCastExceptions):

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

Nhưng - Java doesn Không cho phép Object[] được truyền tới double[]. Truyền nó tới Double[] là ok vì Double là một đối tượng chứ không phải nguyên thủy, nhưng giao diện của tôi chỉ định rằng dữ liệu sẽ được trả lại dưới dạng double[].

Vì vậy, tôi có hai câu hỏi:

  1. Có cách nào tôi có thể lấy dữ liệu cột ra khỏi bảng Object[][] và trả lại hàng loạt các nguyên thủy?
  2. Nếu tôi thay đổi giao diện để trả về Double[], sẽ có bất kỳ tác động hiệu suất nào không?
+0

Tại sao bạn cần có dữ liệu là Object [] []? – notnoop

+0

Bảng có thể lưu trữ bất kỳ loại dữ liệu nào: chuỗi, gấp đôi, số nguyên, các loại khác, v.v. – Brian

+0

Sau đó, làm thế nào bạn có thể đảm bảo rằng mảng tại cộtIndex chỉ chứa Doubles/double? – notnoop

Trả lời

31

Thật không may bạn sẽ cần phải lặp qua toàn bộ danh sách và hủy liên kết Double nếu bạn muốn chuyển đổi nó thành double[].

Theo như hiệu suất hoạt động, có một số thời gian liên quan đến boxing và unboxing nguyên thủy trong Java. Nếu tập hợp đủ nhỏ, bạn sẽ không thấy bất kỳ vấn đề hiệu suất nào.

+4

Mặc dù không áp dụng trực tiếp, các bài kiểm tra trong C# về sắp xếp các mảng lớn (một triệu phần tử) với các kiểu nguyên gốc so với các hộp được đóng hộp cho thấy sắp xếp nguyên thủy nhanh gấp 3 lần. Tôi đề cập đến điều này bởi vì nó minh họa chi phí auto-boxing/unboxing có thể đáng kể. – cletus

+0

Chà. Đó là cách đáng kể hơn tôi mong đợi. Tôi sẽ không xem xét 1 triệu một tập nhỏ mặc dù. – jjnguy

3

Nếu bạn muốn trả lại double[], bạn cần phải tạo một new double[], điền vào và trả lại điều đó.

Đó có thể là một quyết định kiến ​​trúc tốt. Trước tiên, không có ý nghĩa gì khi bỏ một số Object[] đến Double[]; nó không thực sự là một mảng của Double bởi vì có thể có Object s trong đó. Thứ hai, nếu bạn trả về mảng trực tiếp, mã người dùng có thể sửa đổi nó và thay đổi cấu trúc bên trong của đối tượng của bạn.

Tác động hiệu suất chính sẽ là trả lại mảng double[], do unboxing và chi phí phân bổ.

7

Bạn có thể sử dụng một cho mỗi vòng lặp để xây dựng một mảng tạm thời có cùng kích thước, sau đó đúc mỗi phần tử riêng lẻ để tăng gấp đôi và nằm trong mảng.

SO:

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

Xin vui lòng sửa tôi nếu tôi sai lầm chết người ở đây.

+0

Điều này thực sự là giải pháp đơn giản hơn những người khác – Ryde

76

Nếu bạn không ngại sử dụng thư viện của bên thứ ba, commons-lang có loại ArrayUtils với các phương pháp khác nhau để thao tác.

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

Ngoài ra còn có phương pháp bổ sung

doubles = ArrayUtils.toObject(d); 

Edit: Để trả lời phần còn lại của câu hỏi. Sẽ có một số chi phí để làm điều này, nhưng trừ khi mảng thực sự lớn, bạn không nên lo lắng về nó. Kiểm tra nó trước để xem nếu nó là một vấn đề trước khi tái cấu trúc.

Triển khai phương pháp bạn đã thực sự hỏi về sẽ cung cấp cho một cái gì đó như thế này.

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

Cảm ơn thông tin mà commons-lang có chức năng đó, nó sẽ rất hữu ích trong tương lai nếu tôi quyết định đi với bất kỳ thư viện nào của bên thứ ba – Brian

+0

Tôi thích câu trả lời này lặp qua. Tốt hơn hết là sử dụng API của bên thứ ba cho mã soạn sẵn như thế này – Richard

+5

bằng cách sử dụng lib của bên thứ ba có thể trông tốt (sau khi tất cả, mã một lớp trông đẹp hơn nhiều so với vòng lặp xấu xí ...) nhưng việc triển khai không khác gì so với chuyển đổi Double-to-double thủ công. Tệ nhất!Thậm chí có một toán tử bậc ba cho mỗi phù thủy lặp lại có thể dẫn đến việc xử lý nhiều máy tính hơn nữa. Quan điểm của tôi là "thích" một giải pháp nên xem xét hiệu suất và tính hữu ích hơn về tính thẩm mỹ mã. :) 2c của tôi. –

0

tôi sẽ thứ hai ArrayUtils trả lời và nói thêm rằng 1,5 autoboxing documentation (via) kinda tiết lộ rằng không có cách nào BUILTIN:

Không có chuyển đổi được phép từ loại mảng SC [] để mảng gõ TC [] nếu không có phép chuyển đổi khác hơn là một sự chuyển đổi chuỗi từ SC để TC

1

tôi không có bất cứ điều gì để thêm vào câu hỏi thực sự vượt quá những gì jjnguy và Eric K oslow nói.

Nhưng chỉ một lưu ý phụ: Bạn đề cập đến truyền một mảng Đối tượng thành mảng Đôi. Sau đây sẽ KHÔNG hoạt động:

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; 

Dòng cuối cùng sẽ ném một ngoại lệ cho lớp học. Mặc dù mọi phần tử trong mảng thực sự là một Double, mảng được tạo ra như là một mảng của các đối tượng, không phải là một mảng của đôi, do đó, các diễn viên là không hợp lệ.

32

Trong Java 8, đây là một-liner:

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

Lưu ý rằng vẫn còn điều này lặp trên mảng ban đầu và tạo một hình mới.

+0

Đây là những gì tôi đang tìm kiếm! –

1

Bạn có thể sử dụng để chuyển đổi ArrayUtils

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

Không cần lặp toàn bộ dữ liệu.

Các vấn đề liên quan