2015-03-11 21 views
10

Có một danh sách các chuỗi, tôi cần phải xây dựng một danh sách các đối tượng có hiệu quả các cặp (string, its position in the list). Hiện tại tôi có mã như vậy bằng cách sử dụng bộ sưu tập của google:Làm thế nào để ánh xạ các phần tử của danh sách tới các chỉ mục của chúng bằng cách sử dụng các luồng Java 8?

public Robots(List<String> names) { 
    ImmutableList.Builder<Robot> builder = ImmutableList.builder(); 
    for (int i = 0; i < names.size(); i++) { 
     builder.add(new Robot(i, names.get(i))); 
    } 
    this.list = builder.build(); 
} 

Tôi muốn thực hiện điều này bằng cách sử dụng luồng Java 8. Nếu không có chỉ số, tôi chỉ có thể làm:

public Robots(List<String> names) { 
    this.list = names.stream() 
      .map(Robot::new) // no index here 
      .collect(collectingAndThen(
        Collectors.toList(), 
        Collections::unmodifiableList 
      )); 
} 

Để có được các chỉ số, tôi sẽ phải làm một cái gì đó như thế này:

public Robots(List<String> names) { 
    AtomicInteger integer = new AtomicInteger(0); 
    this.list = names.stream() 
      .map(string -> new Robot(integer.getAndIncrement(), string)) 
      .collect(collectingAndThen(
        Collectors.toList(), 
        Collections::unmodifiableList 
      )); 
} 

Tuy nhiên, các tài liệu nói rằng chức năng lập bản đồ nên không quốc tịch , nhưng AtomicInteger là trạng thái hiệu quả.

Có cách nào để ánh xạ các phần tử của luồng tuần tự đến vị trí của chúng trong luồng không?

Trả lời

15

Bạn có thể làm một cái gì đó như thế này:

public Robots(List<String> names) { 
    this.list = IntStream.range(0, names.size()) 
         .mapToObj(i -> new Robot(i, names.get(i))) 
         .collect(collectingAndThen(toList(), Collections::unmodifiableList)); 
} 

Tuy nhiên nó có thể không được như hiệu quả tùy thuộc vào việc thực hiện cơ bản của danh sách. Bạn có thể lấy một trình lặp từ IntStream; sau đó gọi số next() trong số mapToObj.

Là một thay thế, thư viện proton-pack xác định chức năng zipWithIndex cho suối:

this.list = StreamUtils.zipWithIndex(names.stream()) 
         .map(i -> new Robot(i.getIndex(), i.getValue())) 
         .collect(collectingAndThen(toList(), Collections::unmodifiableList)); 
+0

Nếu tôi được sử dụng 'tiếp theo()' từ ' Iterator' trong hàm ánh xạ, nó sẽ là trạng thái. 'zipWithIndex' trông thú vị - nó không sử dụng danh sách trực tiếp nên nó sẽ làm việc với bất kỳ luồng nào. Cảm ơn! –

+1

@JaroslawPawlak Đúng vậy. Và có nếu danh sách cơ bản là một 'LinkedList' ví dụ; bạn sẽ có màn trình diễn tồi tệ. 'ZipWithIndex' trả về một luồng với các chỉ mục' Long'; nếu bạn thực sự cần các số nguyên 'Integer', bạn có thể sử dụng phương thức zip bằng cách cung cấp một (có khả năng) vô hạn' IntStream' :-) –

8

Cách dễ nhất là dòng chỉ số:

List<Robot> robots = IntStream.range(0, names.size()) 
           .mapToObj(i -> new Robot(i, names.get(i)) 
           .collect(toList()); 
Các vấn đề liên quan