Java 8 สตรีมคล้ายกับ RxJava หรือไม่
การกำหนดสตรีม Java 8:
คลาสใน
java.util.streamแพ็คเกจใหม่มี Stream API เพื่อรองรับการทำงานในรูปแบบการใช้งานในส่วนขององค์ประกอบ
Java 8 สตรีมคล้ายกับ RxJava หรือไม่
การกำหนดสตรีม Java 8:
คลาสใน
java.util.streamแพ็คเกจใหม่มี Stream API เพื่อรองรับการทำงานในรูปแบบการใช้งานในส่วนขององค์ประกอบ
คำตอบ:
TL; DR : libs การประมวลผลตามลำดับ / สตรีมทั้งหมดจะเสนอ API ที่คล้ายกันมากสำหรับการสร้างไปป์ไลน์ ความแตกต่างอยู่ใน API สำหรับการจัดการหลายเธรดและองค์ประกอบของท่อ
RxJava ค่อนข้างแตกต่างจากสตรีม จากสิ่งต่างๆทั้งหมดของ JDK สิ่งที่ใกล้เคียงกับ rx.Observable มากที่สุดคือjava.util.stream.Collector Stream + CompletableFuture คอมโบ (ซึ่งมีค่าใช้จ่ายในการจัดการกับเลเยอร์ monad พิเศษนั่นคือต้องจัดการกับการแปลงระหว่างStream<CompletableFuture<T>>และCompletableFuture<Stream<T>>)
มีความแตกต่างที่สำคัญระหว่าง Observable และ Stream:
Stream#parallel()แยกลำดับออกเป็นพาร์ติชันObservable#subscribeOn()และObservable#observeOn()อย่า; มันยากที่จะเลียนแบบStream#parallel()พฤติกรรมด้วย Observable ซึ่งครั้งหนึ่งเคยมี.parallel()วิธีการ แต่วิธีนี้ทำให้เกิดความสับสนมากจน.parallel()การสนับสนุนถูกย้ายไปยังที่เก็บแยกต่างหากบน github, RxJavaParallel รายละเอียดเพิ่มเติมอยู่ในคำตอบอื่นStream#parallel()ไม่อนุญาตให้ระบุเธรดพูลที่จะใช้ซึ่งแตกต่างจากวิธี RxJava ส่วนใหญ่ที่ยอมรับ Scheduler ที่เป็นตัวเลือก เนื่องจากสตรีมอินสแตนซ์ทั้งหมดใน JVM ใช้กลุ่ม fork-join เดียวกันการเพิ่ม.parallel()อาจส่งผลต่อพฤติกรรมในโมดูลอื่นของโปรแกรมของคุณโดยไม่ได้ตั้งใจObservable#interval(), Observable#window()และอื่น ๆ อีกมากมาย; ส่วนใหญ่เป็นเพราะ Streams เป็นแบบ pull-based และ upstream ไม่มีการควบคุมเมื่อปล่อยอิลิเมนต์ถัดไป downstreamtakeWhile(), takeUntil()); วิธีแก้ปัญหาการใช้Stream#anyMatch()มี จำกัด : เป็นการดำเนินการของเทอร์มินัลดังนั้นคุณไม่สามารถใช้งานได้มากกว่าหนึ่งครั้งต่อสตรีมObservable#using()); คุณสามารถห่อ IO สตรีมหรือ mutex กับมันและให้แน่ใจว่าผู้ใช้จะไม่ลืมที่จะปลดปล่อยทรัพยากร - มันจะถูกกำจัดโดยอัตโนมัติเมื่อมีการบอกเลิกสมาชิก สตรีมมีonClose(Runnable)เมธอด แต่คุณต้องโทรด้วยตนเองหรือผ่านการลองกับทรัพยากร เช่น. คุณต้องจำไว้ว่าไฟล์ # บรรทัด () จะต้องอยู่ใน block ลองกับทรัพยากรRound-up: RxJava แตกต่างจาก Streams อย่างมาก ตัวเลือก RxJava ที่แท้จริงคือการนำไปใช้งานอื่น ๆ ของReactiveStreamsเช่นส่วนที่เกี่ยวข้องของ Akka
ปรับปรุง มีเคล็ดลับในการใช้พูลการเข้าร่วมที่ไม่ใช่ค่าเริ่มต้นสำหรับStream#parallelดูเธรดพูลที่กำหนดเองใน Java 8 กระแสขนาน
ปรับปรุง จากข้อมูลทั้งหมดที่กล่าวมานี้อ้างอิงจากประสบการณ์ของ RxJava 1.x ตอนนี้RxJava 2.x อยู่ที่นี่คำตอบนี้อาจจะล้าสมัย
Stream.generate()และผ่านSupplier<U>การใช้งานของคุณเองได้เพียงวิธีการง่ายๆเพียงวิธีเดียวที่คุณให้รายการถัดไปในสตรีม มีวิธีอื่นมากมาย หากต้องการสร้างลำดับStreamที่ขึ้นอยู่กับค่าก่อนหน้านี้อย่างง่ายดายคุณสามารถใช้interate()วิธีCollectionได้ทุกstream()วิธีมีและStream.of()สร้าง a Streamจาก varargs หรืออาร์เรย์ ในที่สุดก็ StreamSupportมีการสนับสนุนสำหรับการสร้างกระแสขั้นสูงมากขึ้นโดยใช้ตัวแยกหรือสำหรับชนิดดั้งเดิมของกระแส
takeWhile(), takeUntil());" - JDK9 มีสิ่งเหล่านี้ผมเชื่อว่าในtakeWhile ()และdropWhile ()
Java 8 Stream และ RxJava ดูคล้ายกันมาก พวกเขามีตัวดำเนินการเหมือนกัน (ตัวกรองแผนที่ flatMap ... ) แต่ไม่ได้สร้างขึ้นสำหรับการใช้งานเดียวกัน
คุณสามารถทำงาน asynchonus โดยใช้ RxJava
ด้วยสตรีม Java 8 คุณจะสำรวจรายการในคอลเล็กชันของคุณ
คุณสามารถทำสิ่งเดียวกันได้ใน RxJava (รายการสำรวจของคอลเลกชัน) แต่เนื่องจาก RxJava เน้นงานที่เกิดขึ้นพร้อมกัน, ... , มันใช้การซิงก์, สลัก, ... ดังนั้นงานเดียวกันโดยใช้ RxJava อาจช้ากว่า ด้วย Java 8 สตรีม
RxJava สามารถนำมาเปรียบเทียบได้CompletableFutureแต่นั่นสามารถคำนวณได้มากกว่าหนึ่งค่า
parallelStreamรองรับการซิงโครไนซ์ที่คล้ายกันของการสำรวจเส้นทาง / แผนที่ / การกรองอย่างง่าย ๆ
มีความแตกต่างทางด้านเทคนิคและแนวความคิดเล็กน้อยตัวอย่างเช่น Java 8 สตรีมเป็นแบบใช้ครั้งเดียวลำดับแบบซิงโครนัสของค่าในขณะที่ RxJava Observables สามารถสังเกตได้อีกครั้ง RxJava มีวัตถุประสงค์เพื่อ Java 6+ และทำงานบน Android เช่นกัน
Java 8 Streams นั้นใช้การดึง คุณทำซ้ำมากกว่าสตรีม Java 8 ที่บริโภคแต่ละรายการ และมันอาจเป็นกระแสที่ไม่รู้จบ
RXJava มาObservableจากการพุชแบบเริ่มต้น คุณสมัครเป็นสมาชิก Observable และคุณจะได้รับการแจ้งเตือนเมื่อรายการถัดไปมาถึง ( onNext) หรือเมื่อสตรีมเสร็จสมบูรณ์ ( onCompleted) หรือเมื่อเกิดข้อผิดพลาด ( onError) เพราะObservableคุณได้รับonNext, onCompleted, onErrorเหตุการณ์ที่คุณสามารถทำได้ทำงานที่มีประสิทธิภาพบางอย่างเช่นการรวมที่แตกต่างกันObservableเพื่อหนึ่งใหม่ ( zip, merge, concat) สิ่งอื่นที่คุณสามารถทำได้คือแคชการควบคุมปริมาณ ... และใช้ API เดียวกันมากขึ้นหรือน้อยลงในภาษาต่าง ๆ (RxJava, RX ใน C #, RxJS, ... )
โดยค่าเริ่มต้น RxJava เป็นเธรดเดียว นอกจากว่าคุณจะเริ่มใช้ Schedulers ทุกอย่างจะเกิดขึ้นในเธรดเดียวกัน
คำตอบที่มีอยู่นั้นครอบคลุมและถูกต้อง แต่ไม่มีตัวอย่างที่ชัดเจนสำหรับผู้เริ่มต้น อนุญาตให้ฉันวางรูปธรรมหลังคำเช่น "push / pull-based" และ "re-observable" หมายเหตุ : ฉันเกลียดคำนี้Observable(เป็นสายน้ำเพื่อประโยชน์ของสวรรค์) ดังนั้นจะอ้างถึงกระแส J8 กับ RX
พิจารณารายการจำนวนเต็ม
digits = [1,2,3,4,5]
สตรีม J8 เป็นเครื่องมือในการปรับเปลี่ยนคอลเลกชัน ตัวอย่างเช่นตัวเลขที่สามารถแยกเป็น
evens = digits.stream().filter(x -> x%2).collect(Collectors.toList())
นี่คือแผนที่ของ Python , ตัวกรอง, การลด , การเพิ่มที่ดีมาก (และเกินกำหนดนาน) ไปยัง Java แต่จะเกิดอะไรขึ้นถ้าตัวเลขไม่ได้ถูกเก็บไว้ล่วงหน้า - จะเกิดอะไรขึ้นถ้าตัวเลขนั้นกำลังถูกสตรีมเข้ามาในขณะที่แอพกำลังทำงานอยู่ - เราจะกรองเลขคู่นั้นได้แบบเรียลไทม์ได้หรือไม่
ลองนึกภาพกระบวนการเธรดที่แยกต่างหากกำลังส่งออกจำนวนเต็มแบบสุ่มในขณะที่แอปกำลังทำงาน ( ---หมายถึงเวลา)
digits = 12345---6------7--8--9-10--------11--12
ใน RX evenสามารถตอบสนองต่อแต่ละหลักใหม่และใช้ตัวกรองแบบเรียลไทม์
even = -2-4-----6---------8----10------------12
ไม่จำเป็นต้องเก็บรายการอินพุตและเอาต์พุต หากคุณต้องการรายการผลลัพธ์ก็ไม่มีปัญหาที่สามารถสตรีมได้เช่นกัน ในความเป็นจริงทุกอย่างเป็นกระแส
evens_stored = even.collect()
นี่คือเหตุผลที่คำเช่น "ไร้สัญชาติ" และ "หน้าที่" เกี่ยวข้องกับ RX มากกว่า
RxJava มีความสัมพันธ์อย่างใกล้ชิดกับความคิดริเริ่มของสตรีมปฏิกิริยาและพิจารณาว่าตนเองเป็นการนำไปใช้อย่างง่ายของ API ปฏิกิริยาสตรีม (เช่นเมื่อเทียบกับการดำเนินการสตรีม Akka ) ความแตกต่างที่สำคัญคือลำธารที่ตอบสนองได้รับการออกแบบมาให้สามารถรับมือกับแรงกดดันด้านหลังได้ แต่ถ้าคุณดูที่หน้าลำธารที่มีปฏิกิริยาคุณจะได้รับแนวคิด พวกเขาอธิบายเป้าหมายของพวกเขาสวยดีและลำธารยังมีความสัมพันธ์อย่างใกล้ชิดกับแถลงการณ์ปฏิกิริยา
ชวา 8 ลำธารจะสวยมากการดำเนินงานของคอลเลกชันมากมายที่สวยคล้ายกับScala สตรีมหรือหมายเลขขี้เกียจ Clojure
Java 8 Streams เปิดใช้งานการประมวลผลคอลเลกชันขนาดใหญ่อย่างมีประสิทธิภาพในขณะที่ใช้ประโยชน์จากสถาปัตยกรรมแบบมัลติคอร์ ในทางตรงกันข้าม RxJava ถูกเธรดเดี่ยวโดยค่าเริ่มต้น (ไม่มี Schedulers) ดังนั้น RxJava จะไม่ใช้ประโยชน์จากเครื่องมัลติคอร์เว้นแต่ว่าคุณใช้รหัสนั้นเอง