Java 8 akışları RxJava gözlemlenebilirlerine benzer mi?
Java 8 akışı tanımı:
Yeni
java.util.stream
paketteki sınıflar , öğelerin akışları üzerinde işlevsel tarzdaki işlemleri desteklemek için bir Akış API'sı sağlar.
Java 8 akışları RxJava gözlemlenebilirlerine benzer mi?
Java 8 akışı tanımı:
Yeni
java.util.stream
paketteki sınıflar , öğelerin akışları üzerinde işlevsel tarzdaki işlemleri desteklemek için bir Akış API'sı sağlar.
Yanıtlar:
TL; DR : Tüm dizi / akış işleme kütüphaneleri boru hattı inşası için çok benzer bir API sunmaktadır. Farklılıklar, çoklu iş parçacığı oluşturma ve boru hatlarının bileşimi için API'dadır.
RxJava, Stream'den oldukça farklıdır. Tüm JDK şeyleri arasında, rx.Observable'a en yakın olan belki de java.util.stream.Collector Stream + CompletableFuture combo'dur (ekstra monad katmanıyla uğraşmanın bir maliyeti vardır, yani Stream<CompletableFuture<T>>
ve arasında dönüştürme işlemek zorunda kalır CompletableFuture<Stream<T>>
).
Gözlemlenebilir ve Akış arasında önemli farklılıklar vardır:
Stream#parallel()
bölümlere sekansı böler, Observable#subscribeOn()
ve Observable#observeOn()
yok; Stream#parallel()
Observable ile davranışı taklit etmek zor , bir zamanlar .parallel()
yöntemi vardı, ancak bu yöntem o kadar karışıklığa neden oldu ki, .parallel()
destek github, RxJavaParallel üzerinde ayrı bir depoya taşındı. Daha fazla ayrıntı başka bir cevapta .Stream#parallel()
isteğe bağlı Zamanlayıcı kabul eden RxJava yöntemlerinin çoğundan farklı olarak, bir iş parçacığı havuzu belirtilmesine izin vermez. JVM'deki tüm akış örnekleri aynı çatal birleştirme havuzunu kullandığından, ekleme işlemi .parallel()
programınızın başka bir modülündeki davranışı yanlışlıkla etkileyebilirObservable#interval()
, Observable#window()
ve diğerleri; bunun nedeni çoğunlukla Akımların çekmeye dayalı olması ve akış yukarı bir sonraki öğenin akış aşağısında ne zaman yayılacağı konusunda hiçbir kontrolünün olmamasıdır.takeWhile()
, takeUntil()
); geçici çözüm Stream#anyMatch()
kullanımı sınırlıdır: terminal işlemidir, bu nedenle akış başına bir defadan fazla kullanamazsınızObservable#using()
); IO akışını veya muteksini bununla sarabilir ve kullanıcının kaynağı serbest bırakmayı unutmayacağından emin olabilirsiniz - abonelik sonlandırmasında otomatik olarak atılır; Stream'in onClose(Runnable)
yöntemi var, ancak manuel olarak veya kaynaklarla deneme yoluyla çağırmanız gerekiyor. Örneğin. Dosyalar # hatları () akılda tutmak gerekir gerekir deneyin-ile-kaynaklar blokta içine alınması.Yuvarlama: RxJava, Akışlardan önemli ölçüde farklıdır. Gerçek RxJava alternatifleri ReactiveStreams'in diğer uygulamalarıdır , örneğin Akka'nın ilgili kısmı.
Güncelleme . Varsayılan olmayan çatal birleştirme havuzunu kullanma hilesi var Stream#parallel
, bkz . Java 8 paralel akışında özel iş parçacığı havuzu
Güncelleme . Yukarıdakilerin hepsi RxJava 1.x deneyimine dayanmaktadır. Şimdi RxJava 2.x geldiğine göre , bu cevap güncel olmayabilir.
Stream.generate()
kendi Supplier<U>
uygulamanızı arayabilir ve iletebilirsiniz . Başka yöntemler de var. Kolay bir sekans oluşturmak için Stream
kullanmak, önceki değerlerine bağlıdır interate()
yöntemi, her Collection
bir yer alır stream()
yöntem ve Stream.of()
bir inşa Stream
bir varargs veya dizi den. Son olarak StreamSupport
, ayırıcılar kullanarak daha gelişmiş akış oluşturma veya akış ilkel türleri için destek vardır.
takeWhile()
, takeUntil()
);" - JDK9 bunlara inanıyorum, takeWhile () ve dropWhile ()
Java 8 Stream ve RxJava oldukça benzer görünüyor. Benzeri operatörlere (filtre, harita, flatMap ...) sahiptirler, ancak aynı kullanım için üretilmezler.
RxJava'yı kullanarak eşzamansız görevleri gerçekleştirebilirsiniz.
Java 8 akışı ile koleksiyonunuzun öğelerini gezeceksiniz.
RxJava'da (bir koleksiyonun çapraz öğeleri) hemen hemen aynı şeyi yapabilirsiniz, ancak RxJava eşzamanlı göreve odaklandığından, ..., senkronizasyon, mandal, ... kullanır. Yani RxJava kullanan aynı görev daha yavaş olabilir Java 8 akışı ile.
RxJava ile karşılaştırılabilir CompletableFuture
, ancak bu yalnızca bir değerden fazlasını hesaplayabilir.
parallelStream
basit çapraz geçişler / haritalar / filtreleme vb benzer senkronizasyonunu destekler ..
Birkaç teknik ve kavramsal fark vardır, örneğin, Java 8 akışları tek kullanımlık, çekme tabanlı, eşzamanlı değer dizileriyken, RxJava Gözlemlenebilirler yeniden gözlenebilir, uyarlamalı itme-çekme tabanlı, potansiyel olarak eşzamansız değer dizileridir. RxJava, Java 6+ 'yı hedefler ve Android'de de çalışır.
Java 8 Akışları çekme tabanlıdır. Her öğeyi tüketen bir Java 8 akışı üzerinden yineleme yaparsınız. Ve sonsuz bir akış olabilir.
RXJava Observable
varsayılan olarak itme tabanlıdır. Bir Gözlemlenebilir öğeye abone olursunuz ve bir sonraki öğe geldiğinde ( onNext
) veya akış tamamlandığında ( onCompleted
) veya bir hata oluştuğunda ( onError
) bildirim alırsınız . İle Çünkü Observable
aldığınız onNext
, onCompleted
, onError
olaylar, farklı birleştirme gibi bazı güçlü işlevler yapabilir Observable
(yenisiyle s zip
, merge
,concat
). Yapabileceğiniz diğer şeyler önbellekleme, daraltma, ... Ve farklı dillerde aşağı yukarı aynı API'yı kullanıyor (RxJava, C #'da RX, RxJS, ...)
Varsayılan olarak RxJava tek iş parçacıklıdır. Zamanlayıcıları kullanmaya başlamadığınız sürece her şey aynı iş parçacığında gerçekleşir.
Mevcut cevaplar kapsamlı ve doğrudur, ancak yeni başlayanlar için açık bir örnek bulunmamaktadır. "İtme / çekme tabanlı" ve "yeniden gözlemlenebilir" gibi terimlerin arkasına bir somut koymama izin verin. Not : Terimden nefret ediyorum Observable
(cennet uğruna bir akış), bu yüzden J8 ve RX akışlarına atıfta bulunacağım.
Tamsayıların bir listesini düşünün,
digits = [1,2,3,4,5]
J8 Stream, koleksiyonu değiştirmek için bir yardımcı programdır. Örneğin, rakamlar bile şu şekilde çıkarılabilir:
evens = digits.stream().filter(x -> x%2).collect(Collectors.toList())
Bu temelde Python'un harita, filtre, azaltma , Java'ya çok güzel (ve gecikmiş) bir katkıdır. Peki ya rakamlar vaktinden önce toplanmadıysa - ya uygulama çalışırken rakamlar akıyor olsaydı - çiftleri gerçek zamanlı olarak filtreleyebilirdik.
Uygulama çalışırken ayrı bir iş parçacığı işleminin rasgele zamanlarda tamsayılar çıkardığını düşünün ( ---
zamanı gösterir)
digits = 12345---6------7--8--9-10--------11--12
RX yılında even
edebilirsiniz tepki her yeni rakam ve gerçek zamanlı olarak filtre uygulamak
even = -2-4-----6---------8----10------------12
Giriş ve çıkış listelerini kaydetmeye gerek yoktur. Bir çıktı listesi istiyorsanız , akıcı olmayan bir sorun da yok. Aslında, her şey bir dere.
evens_stored = even.collect()
Bu nedenle "vatansız" ve "işlevsel" gibi terimler RX ile daha fazla ilişkilidir
RxJava aynı zamanda reaktif akışlar girişimi ile yakından ilgilidir ve kendisini reaktif akışlar API'sinin basit bir uygulaması olarak değerlendirir (örneğin Akka akışları uygulamasına kıyasla ). Temel fark, reaktif akışların geri basıncı kaldırabilecek şekilde tasarlanmasıdır, ancak reaktif akışlar sayfasına bir göz atarsanız, fikir elde edersiniz. Hedeflerini oldukça iyi açıklarlar ve akışlar da reaktif manifesto ile yakından ilişkilidir .
Java 8 akışları, Scala Stream veya Clojure tembel seq'e oldukça benzer, sınırsız bir koleksiyonun uygulanmasıdır .
Java 8 Streams, çok çekirdekli mimarilerden faydalanırken gerçekten büyük koleksiyonların verimli bir şekilde işlenmesini sağlar. Buna karşılık, RxJava varsayılan olarak tek programlıdır (Zamanlayıcılar olmadan). Bu nedenle, bu mantığı kendiniz kodlamadığınız sürece RxJava çok çekirdekli makinelerden yararlanmayacaktır.