Chào mừng bạn đến một thế giới với Java 8!
Nó chỉ đưa tôi cả đêm mà không có giấc ngủ để tìm hiểu những gì cần thiết để viết một dòng mã freaking này. Tôi chắc chắn nó đã được ra khỏi một nơi nào đó nhưng tôi không thể tìm thấy nó. Vì vậy, tôi chia sẻ giờ và giờ nghiên cứu của mình, hãy tận hưởng. Woot!
Giả sử:
ArrayList<ArrayList<String>> mainList = new ArrayList<ArrayList<String>>();
// populate this list here
(Hay nói đúng hơn, trong Java 8:
ArrayList<ArrayList<String>> mainList = new ArrayList();
//Populate
)
Sau đó, tất cả các bạn cần là:
String[][] stringArray = mainList.stream().map(u -> u.toArray(new String[0])).toArray(String[][]::new);`
Bam! Một đường thẳng.
Tôi không chắc nó được so sánh nhanh như thế nào với các tùy chọn khác. Nhưng đây là cách hoạt động:
Lấy một luồng mainList
2D ArrayList. Dòng này hơi giống như một Vector nối với một LinkedList và họ đã có một đứa trẻ.Và đứa trẻ đó, sau này trong cuộc sống, đã lên men trên một số NZT-48. Tôi digress; mainList.stream()
đang trả lại luồng gồm ArrayList<String>
yếu tố. Hoặc thậm chí là geekier nói: mainList.stream()
trả về một Stream<ArrayList<String>>
, phân loại.
Gọi hàm .map
trên luồng đó sẽ trả lại luồng mới có nội dung khớp với loại mới được chỉ định bởi các thông số được chuyển vào map
. Chức năng map
này sẽ bí mật từng phần tử trong luồng của chúng tôi cho chúng tôi. Nó có sẵn trong câu lệnh foreach
. Để thực hiện điều này; hàm map
lấy biểu thức lambda làm tham số của nó. A Lambda expression giống như chức năng một dòng đơn giản. Có hai loại dữ liệu gettin' Jiggy wit it. Đầu tiên là loại dữ liệu trong luồng mà nó được gọi là (mainList.stream()
). Loại tiếp theo là loại dữ liệu mà nó sẽ ánh xạ nó ra, nằm ở nửa bên phải của biểu thức lambda: u -> u.toArray(new String[0])
. Ở đây u
là số nhận dạng bạn chọn giống như khi sử dụng câu lệnh foreach
. Nửa đầu tuyên bố điều này như sau: u ->
. Và giống như một số foreach
, biến số u
giờ sẽ là mỗi phần tử trong luồng khi nó lặp qua luồng. Do đó, u
là loại dữ liệu mà các phần tử của luồng ban đầu là vì nó là là chúng. Nửa bên phải của biểu thức Lambda cho thấy phải làm gì với mỗi phần tử: u.toArray(new String[0])
. Với kết quả được lưu trữ ở vị trí hợp pháp của họ trong luồng mới. Trong trường hợp này, chúng ta chuyển đổi nó thành String[]
.. bởi vì sau khi tất cả, đây là mảng 2D String
.. hoặc đúng hơn từ điểm này trong mã, một mảng 1D là String[]
(mảng chuỗi). Hãy nhớ rằng u
cuối cùng là một ArrayList
. Lưu ý, gọi toArray
từ đối tượng ArrayList
sẽ tạo một mảng mới của loại được truyền vào nó. Ở đây chúng tôi vượt qua trong new String[0]
. Do đó, nó tạo ra một mảng mới kiểu String[]
và có chiều dài bằng với chiều dài của ArrayList u
. Sau đó nó điền vào mảng chuỗi mới này với nội dung của ArrayList
và trả về nó. Mà để lại biểu thức Lambda và trở lại thành map
. Sau đó, map
thu thập các mảng chuỗi này và tạo luồng mới với chúng, nó có loại liên quan String[]
và sau đó trả về nó. Do đó, map
trả lại Stream<String[]>
, trong trường hợp này. (Vâng, thực tế nó trả về một Stream<Object[]>
, gây nhầm lẫn và cần chuyển đổi, xem bên dưới)
Do đó chúng tôi chỉ cần gọi toArray
trên luồng chuỗi mới đó. Nhưng gọi số toArray
trên Stream<Object[]>
hơi khác một chút so với gọi số ArrayList<String>
, như chúng tôi đã làm trước đây. Ở đây, chúng ta phải sử dụng một hàm gây nhầm lẫn tham chiếu hàm. Nó lấy loại này: String[][]::new
. Chức năng new
có loại String[][]
. Về cơ bản, vì hàm này được gọi là toArray, nó sẽ luôn là []
của một số loại. Trong trường hợp của chúng tôi vì dữ liệu bên trong là một mảng khác, chúng tôi chỉ thêm vào một số khác []
. Tôi không chắc tại sao NZT-48 lại không làm việc này. Tôi đã có thể mong đợi một cuộc gọi mặc định để toArray()
sẽ là đủ, thấy rằng một dòng của nó và tất cả. Luồng cụ thể là Stream<String[]>
. Bất cứ ai biết tại sao map
thực sự trả về một Stream<Object[]>
và không phải là một dòng của kiểu trả về bởi biểu thức Lambda bên trong?
Bây giờ, chúng tôi đã nhận được toArray
từ luồng mainList
hoạt động bình thường của chúng tôi.Chúng tôi chỉ có thể đổ nó vào một biến địa phương dễ dàng đủ: String[][] stringArray = mainList.stream...
Chuyển đổi 2D ArrayList của số nguyên vào mảng 2D ints nguyên thủy
Bây giờ, tôi biết một số bạn được ra khỏi đó đi. "Điều này không làm việc cho ints!" Như trường hợp của tôi. Tuy nhiên, nó hoạt động cho "Ents", xem ở trên. Tuy nhiên, nếu bạn muốn một mảng int
nguyên thủy 2D từ một 2D ArrayList
của Integer
(ví dụ: ArrayList<ArrayList<Integer>>
). Bạn phải thay đổi xung quanh bản đồ [trái đất] giữa đó. Hãy nhớ rằng ArrayLists không thể có các kiểu nguyên thủy. Do đó, bạn không thể gọi số toArray
trên số ArrayList<Integer>
và mong muốn nhận được int[]
. Bạn sẽ cần phải vạch ra nó ... một lần nữa.
int[][] intArray = mainList.stream().map( u -> u.stream().mapToInt(i->i).toArray() ).toArray(int[][]::new);
Tôi đã cố gắng giải phóng nó để dễ đọc. Nhưng bạn có thể thấy ở đây rằng chúng ta phải trải qua toàn bộ quá trình lập bản đồ một lần nữa. Lần này chúng ta không thể chỉ đơn giản gọi toArray
trên ArrayList u
; như với ví dụ trên. Ở đây, chúng tôi đang gọi số toArray
trên số Stream
không phải là ArrayList
. Vì vậy, vì một lý do nào đó, chúng tôi không phải chuyển nó thành "loại", tôi nghĩ rằng nó dùng steroid của nó. Do đó, chúng tôi có thể chọn tùy chọn mặc định; nơi nó có một hit của NZT-48 và con số ra rõ ràng đối với chúng tôi [run] thời gian này. Tôi không chắc tại sao nó không thể làm điều đó trong ví dụ trên. Oh, thats right .... ArrayLists không dùng NZT-48 như Streams. Chờ đã ... tôi còn nói gì nữa?
Annnyhoow, vì luồng thông minh. Giống như Sheldon, chúng tôi cần một giao thức hoàn toàn mới để giải quyết chúng. Rõ ràng trí thông minh tiên tiến không phải lúc nào cũng dễ dàng giải quyết. Do đó, cần có mapToInt
mới để tạo Stream
mới mà chúng tôi có thể sử dụng thông minh toArray
thông minh hơn. Và biểu thức Lambda i->i
Lambda trong mapToInt
là một unboxing đơn giản của Integer
đến int
, bằng cách sử dụng tính năng tự động mở hộp ẩn cho phép int = Integer
. Mà, bây giờ, có vẻ như một điều tầm thường câm để làm, như thể trí thông minh có giới hạn của nó. Trong cuộc phiêu lưu của tôi học tất cả những điều này: Tôi thực sự đã cố gắng sử dụng mapToInt(null)
vì tôi đã mong đợi một hành vi mặc định. Không phải là một đối số !! (ho Sheldon ho) Sau đó, tôi nói trong cô gái giọng Husker thung lũng hết sức mình, "Afterall, nó là gọi mapToInt
, tôi sẽ đoán rằng, giống như, 84% thời gian (42 x2) nó sẽ được, như, đã thông qua i->i
bởi, giống như, tất cả mọi người, giống như, omgawd! " Không cần phải nói, tôi cảm thấy một chút ... như .. this guy. Dunno tại sao nó không hoạt động theo cách đó!
Vâng, tôi là mắt đỏ và nửa mê sảng và nửa ngủ. Tôi có thể đã phạm một số sai lầm; xin vui lòng troll chúng ra để tôi có thể sửa chữa chúng và cho tôi biết nếu có một cách tốt hơn!
PT
gì nếu tôi có ArrayList và muốn chuyển đổi nó thành một 2D mảng ? –
shridatt
xin lỗi, tôi đã bỏ lỡ điều này, bạn có thể đã tìm ra nó ngay bây giờ ... Dù sao, nó chỉ đơn giản là 'String [] [] array2D = new String [arrayList.size()] []; cho (int i = 0; i