2016-03-01 26 views
29

Tôi có Danh sách các SourceObject và tôi cần phải chuyển đổi nó thành Danh sách ResultObjects.RxJava: Cách chuyển đổi Danh sách đối tượng thành Danh sách đối tượng khác

Tôi có thể lấy một đối tượng khác phương pháp sử dụng của ResultObject:

convertFromSource(srcObj); 

dĩ nhiên là tôi có thể làm điều đó như thế này:

public void onNext(List<SourceObject> srcObjects) { 
    List<ResultsObject> resObjects = new ArrayList<>(); 
    for (SourceObject srcObj : srcObjects) { 
     resObjects.add(new ResultsObject().convertFromSource(srcObj)); 
    } 
} 

nhưng tôi sẽ rất trân trọng cho những người có thể hiển thị cách thực hiện tương tự bằng cách sử dụng rxJava.

Trả lời

40

Nếu Observable của bạn phát ra một List, bạn có thể sử dụng các nhà khai thác:

  • flatMapIterable (chuyển đổi danh sách của bạn đến một Quan sát các hạng mục)
  • map (chuyển đổi mục của bạn để mục khác)
  • toList toán tử (chuyển một Quan sát hoàn thành thành Quan sát phát ra danh sách các mục từ Hoàn thành có thể quan sát)

    Observable<SourceObjet> source = ... 
    source.flatMapIterable(list -> list) 
         .map(item -> new ResultsObject().convertFromSource(item)) 
         .toList() 
         .subscribe(transformedList -> ...); 
    
+12

Điều này trông thực sự sạch sẽ, mặc dù có một số nhược điểm. 1. Nếu nguồn phát ra nhiều hơn một danh sách, tất cả chúng sẽ được làm phẳng bởi 'flatMapIterable' thành một dòng các đối tượng và' toList() 'sẽ thu thập chúng trong một danh sách duy nhất. Vì vậy, nếu bạn quan tâm đến nhiều phát thải và giữ chúng trong các danh sách riêng biệt, thì rất tiếc là bạn đã mất điều này. 2. 'toList()' chờ cho nguồn có thể quan sát được, vì vậy nếu bạn làm điều đó trên một quan sát vô hạn (giống như một ràng buộc với các sự kiện UI), bạn sẽ không bao giờ nhận được bất cứ điều gì trong 'subscribe()' của bạn. –

+0

@ MarcinKoziński bạn sẽ giải quyết nr như thế nào. 2? Tôi đang gặp tình huống .toList không trả lại bất cứ điều gì. Cảm ơn –

+2

Tôi nghĩ bạn chỉ cần sử dụng một cách tiếp cận khác. Nếu bạn đang cố chuyển đổi từng phần tử của một danh sách, bạn có thể phải thực hiện '.map (list ->/* xây dựng một danh sách mới bằng cách sử dụng đồng bộ cũ cho vòng lặp * /)'. Hoặc sử dụng bất kỳ cách tiếp cận nào khác để chuyển đổi danh sách của bạn bên trong '.map()'. Nếu không, bạn có thể sử dụng toán tử như '.take (itemCount)' trên quan sát vô hạn của bạn để làm cho nó hữu hạn. Lưu ý rằng điều này rõ ràng sẽ giảm tất cả các phần tử sau 'itemCount', do đó có thể không phải là những gì bạn muốn. –

0

Bạn có thể sử dụng toán tử map. Ví dụ, nếu bạn có danh sách s các số nguyên và bạn muốn chuyển đổi vào danh sách s của đôi:

List<Integer> li = new ArrayList<>(); 
    Observable.just(li).map(l -> { 
     List<Double> lr = new ArrayList<Double>(); 
     for(Integer e:l) { 
      lr.add(e.doubleValue()); 
     } 
     return lr; 
    }); 

Nhưng tất cả đó là rất nhiều tự nhiên hơn nếu bạn có thể kiểm soát các quan sát và thay đổi nó để quan sát đơn thay vì các bộ sưu tập. Cùng một mã có thể chuyển đổi các yếu tố số nguyên duy nhất vào những đôi:

Observable.just(1,2,3).map(elem -> elem.doubleValue()) 
+0

Sẽ không 'chỉ (li) 'phát ra một một mục (danh sách), không phải mọi phần tử từ danh sách như 'from (li)'? –

+0

@ cricket_007 Có, nhưng như tôi hiểu về vấn đề Yura muốn phát ra danh sách không có phần tử nào trong danh sách (Nó sử dụng onNext (List)). Như tôi đã nói trong phản ứng của tôi nó không phải là tự nhiên hơn, nhưng đôi khi có thể là những gì bạn muốn. – lujop

11

Phương pháp Observable.from() factory cho phép bạn chuyển đổi một tập hợp các đối tượng vào một dòng quan sát được. Khi bạn có một luồng, bạn có thể sử dụng toán tử map để chuyển đổi từng mục được phát ra. Cuối cùng, bạn sẽ phải đăng ký vào các kết quả quan sát ở để sử dụng các mục chuyển:

// Assuming List<SourceObject> srcObjects 
Observable<ResultsObject> resultsObjectObservable = Observable.from(srcObjects).map(new Func1<SourceObject, ResultsObject>() { 
    @Override 
    public ResultsObject call(SourceObject srcObj) { 
     return new ResultsObject().convertFromSource(srcObj); 
    } 
}); 

resultsObjectObservable.subscribe(new Action1<ResultsObject>() { // at this point is where the transformation will start 
    @Override 
    public void call(ResultsObject resultsObject) { // this method will be called after each item has been transformed 
     // use each transformed item 
    } 
}); 

Các phiên bản rút gọn nếu bạn sử dụng lambdas sẽ trông như thế này:

Observable.from(srcObjects) 
    .map(srcObj -> new ResultsObject().convertFromSource(srcObj)) 
    .subscribe(resultsObject -> ...); 
3

Đừng phá vỡ chuỗi, giống như thế này.

Observable.from(Arrays.asList(new String[] {"1", "2", "3", })) 
.map(s -> Integer.valueOf(s)) 
.reduce(new ArrayList<Integer>, (list, s) -> { 
    list.add(s); 
    return list; 
}) 
.subscribe(i -> { 
    // Do some thing with 'i', it's a list of Integer. 
}); 
+1

Thay vì 'reduce' bạn có thể sử dụng' toList() 'cho một mã sạch hơn. – Anyonymous2324

+0

Cảm ơn bạn rất nhiều, toList() thực sự là một ý tưởng hay. – AtanL

+0

Trên thực tế, có vấn đề với 'toList' như được mô tả trong bình luận ở trên. giảm giải quyết chúng http://stackoverflow.com/questions/35734060/rxjava-how-to-convert-list-of-objects-to-list-of-another-objects#comment62270275_35750170 – tasomaniac

20

Nếu bạn muốn duy trì Lists phát ra bởi nguồn Observable nhưng chuyển đổi các nội dung, tức là Observable<List<SourceObject>> để Observable<List<ResultsObject>>, bạn có thể làm một cái gì đó như thế này:

Observable<List<SourceObject>> source = ... 
source.flatMap(list -> 
     Observable.fromIterable(list) 
      .map(item -> new ResultsObject().convertFromSource(item)) 
      .toList() 
      .toObservable() // Required for RxJava 2.x 
    ) 
    .subscribe(resultsList -> ...); 

Điều này đảm bảo một cặp vợ chồng của sự vật:

  • Số lượng Lists phát ra bởi các Observable được duy trì. I E.nếu nguồn phát ra 3 danh sách, sẽ có 3 danh sách chuyển đổi ở đầu bên kia
  • Sử dụng Observable.fromIterable() sẽ đảm bảo các nội Observable chấm dứt để toList() thể được sử dụng
Các vấn đề liên quan