Akışları normalde Koleksiyonlar döndüreceğimiz yere döndürmek akılcı bir şey mi?


19

Herhangi bir eski koda bağlı olmayan API'mı geliştirirken, genellikle sonuçları toplayarak tamamen Streams pipeline olan sonlandırılmış yöntemler yazıyorum. Bunun gibi:

ImmutableSet<T> deriveSomethingMeaningfulFromPrivateState() {
    return myPrivateThingies.stream()
        .map(this::ownerOfThing)
        .map(Owner::socialStatus)
        .filter(SocialStatus::isHeAFineMatey)
        .collect(MyCustomCollectors.toImmutableSet());
}

Şimdi, bu sınıftaki müşterilerin çoğu genellikle öğeleri aramak ve yinelemek için Koleksiyona (bu durumda bir ImmutableSet) ihtiyaç duyacaktır, ancak bazı istemciler bir Akışa sahip olmaktan yararlanabilir, böylece bunun üzerine daha fazla işlem yapabilirler. Koleksiyondan yeni bir akış edinmeye gerek kalmadan akış gerçekleştirin. Bu nedenle, bir Akışa geri dönmek, müşterilere Koleksiyona sahip olmaları durumunda sahip olacakları bir seçenekler kümesi sunar (sonuçta, her zaman Akışın collect()kendileri olabilirler:

Stream<T> deriveSomethingMeaningfulFromPrivateState() {
    return myPrivateThingies.stream()
        .map(this::ownerOfthing)
        .map(Owner::socialStatus)
        .filter(SocialStatus::isHeAFineMatey);
        // No collect
}

Bu yaklaşım, deneyebileceğim herhangi bir potansiyel kusur görmediğim için denemek için cazip geliyor. Ancak, herhangi bir kütüphanede bu yaklaşımı hiç görmedim (muhtemelen Java 8'in ortaya çıkmasından sonra pek çok kütüphane yayınlanmadığı için), bu yüzden benimsemekten biraz korkuyorum. Mevcut kütüphane sınıfları genellikle özel durumdan bir şey türettiklerinde Koleksiyonları döndürür.

Java-8 öncesi kendimin bir Koleksiyon döndüreceği her yere bir Akış döndürmeye karar verirsem olabilecek kötü bir şey var mı ? Ya da büyük olasılıkla burada özel devletten türeyen bir antipattern bir şey mi yapıyorum?

Yanıtlar:


14

Eğer myPrivateThingiesdeğişebilirdir sayede kendi özel durumuna ve akarsu sonuçları arasında bir gizli bağımlılığı oluşturduk. Müşterinin dolaylı olarak myPrivateThingiesdurum değiştirmesine neden olması mümkünse , o zaman arama yaparken collectilk olarak vermeyi düşündüğünüzden farklı bir sonuç alacaktır .

Eğer myPrivateThingiesdeğişmez, sonuç referentially şeffaf olacaktır, ancak dikkat etmek zorunda tane daha mesele var: semantik çöp , yani artık gerekli olmayan büyük miktarda bellek tutunarak. Diyelim ki myPrivateThingiesçok büyük ve akışın toplanmasının sonucu küçük. Müşteri, nesneyi üreten nesneye yapılan tüm atıfları kaldırdıktan sonra uzun süre beklemeye devam edebilir, ancak streamyine de myPrivateThingiesçöp toplanmaya devam etmez . Sonuçların hevesle toplanması myPrivateThingiesserbest bırakılabilir.

Bu aslında arama yaparken Java 7'den önce oldu substring. Oracle, alt dizeyi her seferinde kopyalamamaktan kaynaklanan potansiyel verimlilik tasarruflarının, aşırı bellek tüketimi ile ortalama kullanıcıyı şaşırtmaya değer olmadığına karar verdi. Bu, eski davranış (örneğin ayrıştırıcılar) için gerçek kullanım durumlarının olmadığı anlamına gelmez, ancak genellikle sonuçları hevesle toplamak yeterince hızlıdır ve bu olduğunda hiçbir avantajınız ve potansiyel bir konunuz yoktur.

Öte yandan, bir akışın geri döndürülmesi, istemciye, onun için bir tane seçmeniz yerine, sonuçları tutmak için hangi veri yapısını kullanmak istediklerini seçme yeteneği verir. Her iki seçeneği de sunmaya değer.


4

Dikkate alınması gereken en önemli şey: Streams yalnızca bir kez yinelenebilir, ancak a üzerinde daha fazla esnekliğe sahip Collectionolursunuz: sonuçlar üzerinde ek, tekrarlayan işlemler yapmak için daha fazla Streams veya hatta Iterators oluşturmaya devam edebilirsiniz .

Bu nedenle, yöntemi arayanların sonuçları bir kez ve sadece bir kez kullanıp kullanmayacaklarından emin değilseniz, a değerini döndürmek daha iyidir Collection.


Örnek kodunuzda bariz bir hata var: Neden SocialStatusbir kişi kavramı var he?


3

Bana göre hayır. Akarsu ile yapabileceğiniz şeyler, koleksiyonlarla yapabileceğiniz şeylerin katı bir üst kümesidir ve genellikle daha verimli hale getirilebilirler, bu yüzden bunları yabancılardan başka kullanmamanız için bir neden yoktur. "Lambda ifadeleri Java 8'in ağ geçidi ilacıdır, ancak Akışlar gerçek bağımlılıktır." (Venkat Subramaniam, Java'da Fonksiyonel Programlama )

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.