RxJava'da flatmap ve switchmap arasındaki fark nedir?


149

Rxjava doc switchmap tanımı oldukça muğlak ve kendisine bağlanan aynı sayfada flatmap olarak. İki operatör arasındaki fark nedir?


1
Bu konuda flatmap ile aynı sayfaya bağlantı verir . Gerçekten doğrudur. Ancak Dile Özel Bilgiler bölümüne gidin ve ilginç bir operatör açın. Bunun otomatik olarak TOC'den yapılması gerektiğini düşünüyorum, ama ... Aynı resmi javadoc'ta da görebilirsiniz .
Ruslan Stelmachenko

Yanıtlar:


180

Belgelere göre ( http://reactivex.io/documentation/operators/flatmap.html )

switchMapgibidir flatMap, ancak yeni bir olay kaynağı gözlemlenebilir yayılan kadar yalnızca yeni gözlemlenebilir öğeleri çıkarır.

Mermer diyagramı iyi gösteriyor. Diyagramlardaki farka dikkat edin:

Gelen switchMapikinci orijinal emisyon ( yeşil mermer ), ikinci yaymaz eşlenen emisyon ( yeşil kare üçüncü beri), orijinal emisyon ( mavi mermer ) başlamış ve zaten ilk yayılan etti eşlenen emisyon ( mavi elmas ). Başka bir deyişle, iki eşlenmiş yeşil emisyondan sadece ilki gerçekleşir; hiçbir mavi kare yayılmaz çünkü mavi elmas onu döver.

İçinde flatMap, "eski" olsalar bile, eşlenen tüm sonuçlar yayınlanır. Diğer bir deyişle, hem birinci ve ikinci eşlenen yeşil emisyonları meydana - Bir yeşil kare yayılan oldum olacak (onlar tutarlı haritası işlevini kullanıp kullanmadığı; etmediler beri, gördüğünüz ikinci onu yayılan olsa bile, yeşil elmas sonra ilk mavi elmas)

switchMap orijinal gözlemlenebilir yeni bir şey yayarsa, önceki emisyonlar artık eşlenebilir gözlenebilir üretmez;  bu eski sonuçları önlemek için etkili bir yoldur

düz harita

orijinal gözlemlenebilir yeni bir şey yayarsa, önceki emisyonlar artık eşlenebilir gözlenebilir üretmez;  bu eski sonuçları önlemek için etkili bir yoldur


4
Teşekkürler, diyagram çok yararlı. SwitchMap'in kullanılacağı gerçek bir dünya örneği biliyor musunuz?
Julian Go

1
: @JulianGo orada burada bir örnek github.com/samuelgruetter/rx-playground/blob/master/... O kullanır .map(func).switch, ama bu aynı şey .switchMap(func).
Samuel Gruetter

2
Birisinin hala switchMap'in gerçek bir dünya örneğine ihtiyacı olması durumunda, bu bağlantı bağlantısını izleyebilir ve flatMap yerine swicthMap'in ne zaman kullanılacağını anlayacaktır.
hermannovich

2
Ben Lesh'ten RxJs5 kullanarak SwitchMap kullanan bir örnek için - 25-26. dakikaları burada görebilirsiniz - youtube.com/watch?v=3LKMwkuK0ZE benim için, flatmap zaten anlaşıldı ...
arcseldon

7
Mermer diyagram iyi gösteriyor? Ne? Sanırım geçiş haritasını zaten anlıyorsanız belki.
17'de Helzgate

166

Ben "anında arama" - yani kullanıcı bir metin kutusuna yazarken ve sonuçları her tuş vuruşu ile neredeyse gerçek zamanlı olarak görünen zaman bu rastladım. Çözüm şöyle görünüyor:

  1. Dize PublishSubject gibi bir konu var
  2. Metin kutusunda geri aramayı değiştir, .onNext (text)
  3. hız sınırı sunucu sorgularına .debounce filtresi uygula
  4. bir sunucu sorgusu gerçekleştirmek için .switchMap uygula - arama terimini al ve SearchResponse'nin Gözlenebilir'i döndürme
  5. .subscribe öğesini SearchResponse kullanan ve kullanıcı arayüzünü güncelleyen bir yöntemle uygulayın.

FlatMap ile, arama sonuçları eski olabilir, çünkü arama yanıtları düzensiz olabilir. Bunu düzeltmek için, daha yeni bir tane sağlandığında eski bir gözlemlenebilirliğin aboneliğinin kaldırılmasını sağladığından switchMap kullanılmalıdır.

Bu nedenle, özet olarak, flatMap zamanlamaları ne olursa olsun tüm sonuçlar önemli olduğunda kullanılmalı ve switchMap yalnızca son Gözlenebilir konudan sonuçlar alındığında kullanılmalıdır.



95

Hayır flatMap tartışma karşılaştıran ve kontrast olmadan tamamlandı switchMap, concatMapve concatMapEager.

Tüm bu yöntemler Func1, akımı Observabledaha sonra yayılan s'ye dönüştüren bir yöntem alır ; fark, geri gönderilenlerin Observableabone olduğu ve abone olmadığı ve söz Observablekonusu ____Mapoperatörlerin emisyonlarının söz konusu operatör tarafından yayılıp yayılmadığı ve ne zaman yayıldığıdır .

  • flatMapObservablemümkün olduğunca çok sayıda yayına abone olur . (Platforma bağlı bir sayıdır. Örneğin Android'de daha düşük bir sayı) Sipariş önemli olmadığında ve ASAP emisyonu istediğinizde bunu kullanın.
  • concatMapbirinciye abone olur Observableve yalnızca Observablebir öncekini tamamladığında diğerine abone olur . Sipariş önemli olduğunda ve kaynakları korumak istediğinizde bunu kullanın. Mükemmel bir örnek, önce önbelleği kontrol ederek bir ağ aramasının ertelenmesidir. Bunu, gereksiz çalışmalardan kaçınmak için tipik olarak bir .first()veya .takeFirst()izleyebilir.

    http://blog.danlew.net/2015/06/22/loading-data-from-multiple-sources-with-rxjava/

  • concatMapEageraynı şekilde çalışır ancak mümkün olduğunca çok aboneye (platforma bağlı) abone olur, ancak yalnızca bir önceki Observabletamamlandıktan sonra yayılır . Yapılması gereken çok sayıda paralel işlemeye sahip olduğunuzda mükemmeldir, ancak (flatMap'ten farklı olarak) orijinal siparişi korumak istersiniz.

  • switchMapen son Observablekarşılaştığına abone olur ve önceki tüm aboneliklerden çıkar Observable. Bu, arama önerileri gibi durumlar için idealdir: bir kullanıcı arama sorgusunu değiştirdiğinde, eski istek artık herhangi bir ilgi alanına girmez, bu nedenle abonelikten kaldırılır ve iyi davranan bir Api uç noktası ağ isteğini iptal eder.

Başka bir iş parçacığı Observableolmayan s döndürüyorsanız subscribeOn, yukarıdaki yöntemlerin hepsi aynı şekilde davranabilir. Yuvalanmış Observables'nin kendi iş parçacıkları üzerinde hareket etmesine izin verdiğinizde ilginç ve kullanışlı davranış ortaya çıkar . Sonra paralel çalışılan pek çok yarar elde alabilirsiniz ve akıllıca aboneliği iptal veya gelen abone değil Observablesizin ilgilendirmiyor s Subscribers

  • ambilgi çekici olabilir. Herhangi bir sayı verildiğinde, bir şey yayan Observableilk öğe Observableyayar. Aynı şeyi döndürebilen / döndürmesi gereken birden fazla kaynağınız olduğunda ve performans istediğinizde bu yararlı olabilir. örneğin sıralama, ambbir birleştirme sıralaması ile hızlı bir sıralama ve hangisinin daha hızlı olduğunu kullanabilirsiniz.

1
If you are returning Observables that don't subscribeOn another thread, all of the above methods may behave much the same.- daha switchMap vs flatMapönce karşılaştığım her açıklama, bu önemli yönü kaçırdı, şimdi her şey daha net. Teşekkür ederim.
Andy Res

55

switchMap kez çağrıldı flatMapLatest RxJS 4'te.

Temel olarak sadece en son Gözlemlenebilir olaylardan geçer ve bir öncekinden aboneliği iptal eder.


@EpicPandaForce combineLatest ile tutarsız olmasına rağmen, bir kaynak gözlemlenebilir yayıldığında (bir kez yayılmadan) en son değerleri yayar.
Michael Fry

2
Kısmen switchMap olarak adlandırılmasının nedeni, bu operatörü o.map (...). Switch () kullanarak kendiniz uygulayabilmenizdir. O zaman dilin bu kadar kolay yuvarlanmadığı anlaşılan mapSwitch olacağını hayal ederdim.
Niall Connaughton

7

Harita, FlatMap, ConcatMap ve SwitchMap bir işlev ya da değiştirir bir gözlemlenebilir tarafından yayılan veri uygular.

  • Harita , bir Gözlemlenebilir kaynağı tarafından yayılan her öğeyi değiştirir ve değiştirilen öğeyi yayar.

  • FlatMap, SwitchMap ve ConcatMap ayrıca her yayılan öğe üzerinde bir işlevi uygular ancak bunun yerine değiştirilmiş öğe döndürmek, veriyi tekrar yayarlar hangi kendisi gözlemlenebilir döndürür.

  • FlatMap ve ConcatMap çalışmaları hemen hemen aynıdır. Birden fazla Gözlenebilir tarafından yayılan öğeleri birleştirir ve tek bir Gözlenebilir öğeyi döndürür.

  • FlatMap ve ConcatMap arasındaki fark , öğelerin yayınlanma sırasıdır.
  • FlatMap , yayma sırasında öğelere serpiştirebilir, yani yayılan öğelerin sırası korunmaz.
  • ConcatMap öğelerin sırasını korur. Ancak ConcatMap'in ana dezavantajı, her bir Gözlemlenebilir'in işini tamamlamasını beklemesi gerektiğinden asenkron korunmaz.
  • SwitchMap biraz farklıdır FlatMap ve ConcatMap . SwitchMap önceki kaynaktan aboneliği iptal eder Yeni öğe yayılmaya başladığında gözlemlenebilir, böylece her zaman geçerli Gözlemlenebilir öğeden yayılır.

1

Örnek bir kod arıyorsanız

/**
 * We switch from original item to a new observable just using switchMap.
 * It´s a way to replace the Observable instead just the item as map does
 * Emitted:Person{name='Pablo', age=0, sex='no_sex'}
 */
@Test
public void testSwitchMap() {
    Observable.just(new Person("Pablo", 34, "male"))
              .switchMap(person -> Observable.just(new Person("Pablo", 0, "no_sex")))
              .subscribe(System.out::println);

}

Burada daha fazla örnek görebilirsiniz https://github.com/politrons/reactive


4
Ancak switchMap'in onu flatMap'ten ayıran temel özelliğini kaçırırsınız - yalnızca en son Gözlemlenebilir konular, bir öncekinden ayrılırken.
Artem Novikov

3
Değiştirmeye Bu örnekte, switchMapile flatMaptam olarak aynı şekilde çalışacaktır.
Piotr Wittchen

1

İşte bir tane daha - 101 satır uzunluğunda örnek . Bu benim için bir şeyi açıklıyor.

Söylendiği gibi: son gözlemlenebilir (eğer en yavaş olanı) alır ve gerisini görmezden gelir.

Sonuç olarak:

Time | scheduler | state
----------------------------
0    | main      | Starting
84   | main      | Created
103  | main      | Subscribed
118  | Sched-C-0 | Going to emmit: A
119  | Sched-C-1 | Going to emmit: B
119  | Sched-C-0 | Sleep for 1 seconds for A
119  | Sched-C-1 | Sleep for 2 seconds for B
1123 | Sched-C-0 | Emitted (A) in 1000 milliseconds
2122 | Sched-C-1 | Emitted (B) in 2000 milliseconds
2128 | Sched-C-1 | Got B processed
2128 | Sched-C-1 | Completed

A'nın görmezden geldiğini görüyorsunuz.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.