2015-12-11 29 views
10

Tôi có một chuỗi duy nhất của định dạng:Java 8 suối trên mảng chuỗi

row1col1 row1col2 
row2col1 row2col2 
row3col1 row3col2 

và vân vân ...

tôi muốn trích xuất từng hạng mục và xây dựng một mảng của các đối tượng với các thuộc tính như thế này :

new MyObject(row1col1, row1col2); 

Tôi mới dùng Java 8 và Luồng và tôi muốn tìm hiểu cách tôi có thể đạt được điều này mà không có vòng lặp.

Thông thường tôi sẽ sử dụng một String.split('\n') cho tích lũy hàng vào một mảng String

Và sau đó một vòng nơi cho mỗi dòng tôi sẽ chia một lần nữa trên tách không gian và với các mảng kết quả của hai yếu tố (row1col1 row1col2) xây dựng đối tượng của tôi, cho đến khi không còn hàng nào để xử lý.

Như thế này:

String sausage = "row1col1 row1col2\nrow2col1 row2col2\nrow3col1 row3col2"; 
String[] rows = sausage.split("\n"); 

for (String row : rows) { 
    String[] objectData = u.split("\\s+"); 
    MyObject myObject = new MyObject(objectData[0], objectData[1]); 
    myObjectList.add(myObject); 
} 

bất cứ ai có thể giải thích cho tôi làm thế nào để đạt được cùng với con suối và những gì là cơ chế đằng sau đó cho phép tôi làm như vậy?

Đây có phải là cách suy nghĩ hợp lý khi tăng số lượng các phần tử hay không vì tất cả các ví dụ tôi đã thấy luồng tập trung vào lọc, thu thập hoặc nói chung cho một tập hợp các phần tử lấy một tập nhỏ áp dụng một số tiêu chí.

+2

Bạn có muốn toàn bộ dòng được bộ nhớ như một mảng, hoặc bạn muốn xử lý một rowset tại một thời điểm, và lặp lại vòng lặp xử lý một hàng tại một thời điểm? – Tschallacka

+0

Tôi thực sự tải luồng từ một tệp, vì vậy tôi nghĩ rằng nó được đọc tất cả trong bộ nhớ trước khi được xử lý đúng không? –

+0

@LucianEnache, không nhất thiết. Phụ thuộc vào cách bạn đang đọc. – shmosel

Trả lời

11

Một cách đơn giản là tạo một Pattern bằng dấu tách dòng và chia đầu vào String thành Stream. Sau đó, mỗi dòng được chia với một khoảng trắng (chỉ giữ 2 phần) và ánh xạ tới một số MyObject. Cuối cùng, một mảng được xây dựng với kết quả.

public static void main(String[] args) { 
    String str = "row1col1 row2col2\r\nrow2col1 row2col2\r\nrow3col1 row3col2"; 

    MyObject[] array = 
     Pattern.compile(System.lineSeparator(), Pattern.LITERAL) 
       .splitAsStream(str) 
       .map(s -> s.split("\\s+", 2)) 
       .map(a -> new MyObject(a[0], a[1])) 
       .toArray(MyObject[]::new); 

    System.out.println(Arrays.toString(array)); 
} 

Sử dụng splitAsStream thể được thuận lợi hơn Stream.of(...) nếu đầu vào String dài.

Tôi giả định trong mã rằng dấu tách dòng của String là dấu phân tách dòng mặc định (System.lineSeparator()) của hệ điều hành nhưng bạn có thể thay đổi điều đó nếu không.


Thay vào đó, nếu bạn đang đọc từ một tập tin, bạn có thể sử dụng Files.lines() để có được một tổ chức của một Stream của tất cả các dòng trong file:

MyObject[] array = Files.lines(path) 
         .map(s -> s.split("\\s+", 2)) 
         .map(a -> new MyObject(a[0], a[1])) 
         .toArray(MyObject[]::new); 

System.out.println(Arrays.toString(array)); 
5

Bạn có thể tạo ra một Stream của String s đại diện cho một MyObject trường hợp duy nhất, và biến đổi mỗi người trong số họ MyObject dụ của bạn (bằng cách đầu tiên tách chúng một lần nữa và sau đó xây dựng một trường hợp MyObject):

List<MyObject> list = 
    Stream.of(inputString.split("\n")) 
     .map (s -> s.split(" ")) 
     .filter (arr -> arr.length == 2) // this validation may not be necessary 
             // if you are sure each line contains 2 tokens 
     .map (arr -> new MyObject(arr[0],arr[1])) 
     .collect(Collectors.toList());