2016-03-01 14 views
29

मेरे पास SourceObjects की सूची है और मुझे इसे परिणाम ऑब्जेक्ट्स की सूची में बदलने की आवश्यकता है।RxJava: वस्तुओं को अन्य वस्तुओं की सूची में बदलने के लिए कैसे करें

convertFromSource(srcObj); 
निश्चित रूप से

मैं इस तरह यह कर सकते हैं:

मैं ResultObject का एक और तरीका का उपयोग करने के एक वस्तु प्राप्त कर सके

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

लेकिन मैं बहुत कोई है जो दिखा सकते हैं करने के लिए सराहना की जाएगी rxJava का उपयोग करके ऐसा कैसे करें।

उत्तर

40

अपने Observable एक List का उत्सर्जन करता है, तो आप इन ऑपरेटरों का उपयोग कर सकते हैं:

  • flatMapIterable (मदों की एक नमूदार के लिए अपनी सूची को बदलने)
  • map (एक और आइटम के लिए अपने मद को बदलने)
  • toList ऑपरेटरों (एक पर्यवेक्षित में एक पूर्ण पर्यवेक्षक को परिवर्तित करें जो पूर्ण पर्यवेक्षण से वस्तुओं की एक सूची उत्सर्जित करता है)

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

यह वास्तव में साफ दिखता है, हालांकि कुछ नुकसान हैं। 1. यदि स्रोत एक से अधिक सूची में उत्सर्जित करता है, तो वे सभी 'flatMapIterable' द्वारा ऑब्जेक्ट्स की एक स्ट्रीम में फ़्लैट किए जा रहे हैं और' toList() 'उन्हें एक सूची में एकत्रित करेंगे। तो यदि आप कई उत्सर्जन की देखभाल करते हैं और उन्हें अलग-अलग सूचियों में रखते हैं, तो दुर्भाग्यवश आप इसे खो देते हैं। 2. 'toList()' पूरा करने के लिए देखे जाने वाले स्रोत के लिए प्रतीक्षा करता है, इसलिए यदि आप इसे अनंत अवलोकन (जैसे यूआई घटनाओं के लिए बाध्य) पर करते हैं, तो आपको कभी भी 'सब्सक्राइब() 'में कुछ भी नहीं मिलेगा। –

+0

@ मार्किनकोज़ीन्स्की आप कैसे हल करेंगे। 2? मुझे स्थिति है जहां। सूची कुछ भी वापस नहीं करती है। धन्यवाद –

+2

मुझे लगता है कि आपको बस एक अलग दृष्टिकोण का उपयोग करने की आवश्यकता है। यदि आप किसी सूची के प्रत्येक तत्व को बदलने की कोशिश कर रहे हैं, तो आपको केवल '.map (list ->/* लूप * /) के लिए सादे पुराने का उपयोग करके एक नई सूची बनाना होगा। या अपनी सूची को '.map()' के अंदर बदलने के लिए किसी भी अन्य दृष्टिकोण का उपयोग करें। अन्यथा आप इसे सीमित करने के लिए अपने अनंत अवलोकन योग्य पर '.take (itemCount)' जैसे ऑपरेटरों का उपयोग कर सकते हैं। ध्यान दें कि यह 'itemCount' के बाद सभी तत्वों को स्पष्ट रूप से छोड़ देता है, ताकि हो सकता है कि आप जो भी चाहते हों। –

0

आप map ऑपरेटर का उपयोग कर सकते हैं। उदाहरण के लिए अगर आपके पास पूर्णांकों की सूची रों और आप सूची युगल के रों कनवर्ट करना चाहते हैं:

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; 
    }); 

लेकिन सभी यह अगर आप नमूदार को नियंत्रित करने और एक निरीक्षण करने के लिए इसे बदल सकते हैं एक बहुत अधिक स्वाभाविक है संग्रह के बजाय तत्व। एक ही कोड है कि डबल लोगों में एक पूर्णांक तत्वों धर्मान्तरित:

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

नहीं 'बस (ली)' फेंकना होगा इस्तेमाल किया जा सकता है एक एकल आइटम (सूची), सूची से प्रत्येक तत्व जैसे 'से (li) '? –

+0

@ cricket_007 हां, लेकिन समस्या के बारे में मेरी समझ के रूप में युरा सूचियों को उत्सर्जित करना चाहता है सूची के कोई तत्व नहीं (यह अगला (सूची) पर उपयोग करता है)। जैसा कि मैंने अपनी प्रतिक्रिया में कहा है कि यह अधिक प्राकृतिक नहीं है, लेकिन कभी-कभी आप जो चाहते हैं वह हो सकता है। – lujop

11

Observable.from() कारखाने पद्धति से आपको एक प्रत्यक्ष धारा में वस्तुओं का संग्रह कन्वर्ट करने के लिए अनुमति देता है। एक बार आपके पास स्ट्रीम हो जाने के बाद आप प्रत्येक उत्सर्जित आइटम को बदलने के लिए map ऑपरेटर का उपयोग कर सकते हैं।

// 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 
    } 
}); 

संक्षिप्त संस्करण यदि आप lambdas का उपयोग इस प्रकार दिखाई देगा:: अंत में, आप बदल आइटम का उपयोग करने के प्रत्यक्ष परिणामस्वरूप की सदस्यता के लिए होगा

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

तोड़ न करें चेन, बस इस तरह।

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

'कम करने' के बजाय आप क्लीनर कोड के लिए 'toList() 'का उपयोग कर सकते हैं। – Anyonymous2324

+0

आपको बहुत धन्यवाद, toList() वास्तव में एक अच्छा विचार है। – AtanL

+0

वास्तव में उपरोक्त इस टिप्पणी में वर्णित 'toList' के साथ समस्याएं हैं। उन्हें हल करता है http://stackoverflow.com/questions/35734060/rxjava-how-to-convert-list-of-objects-to-list-of-another-objects#comment62270275_35750170 – tasomaniac

20

आप Lists स्रोत Observable द्वारा उत्सर्जित बनाए रखेंगे, लेकिन, सामग्री परिवर्तित यानी Observable<List<SourceObject>>Observable<List<ResultsObject>> लिए करना चाहते हैं, तो आप कुछ इस तरह कर सकते हैं:

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 -> ...); 

, तो इसमें कुछ सुनिश्चित करता है चीजों की:

  • की संख्या Observable द्वारा उत्सर्जितबनाए रखा जाता है। अर्थात।यदि स्रोत 3 सूचियों का उत्सर्जन करता है, वहाँ दूसरे छोर
  • Observable.fromIterable() का उपयोग आंतरिक Observable यह सुनिश्चित करेंगे पर 3 तब्दील सूचियों हो जाएगा समाप्त हो जाता है तो यह है कि toList()
संबंधित मुद्दे