Neden Java Akışları kez kapalı?
'Nin yürütme bir boru hattı gibi birçok kez istediğiniz gibi idam edilebilir IEnumerable
,, bir akım olabilir Java sadece bir kez. yineledi aksine C#
Ölümcül bir operasyon için herhangi bir çağrı akışı, kullanılmaz hale kapatır. ''Güç bir sürü alır. özelliği bu
Bunun nedenini tahmin edebiliyorumdeğilteknik. Bu garip bir kısıtlama arkasında tasarım konuları nelerdi?
Edit: bahsettiğim şey göstermek, C Hızlı Sıralama aşağıdaki uygulanmasını değerlendirmek üzere#:
IEnumerable<int> QuickSort(IEnumerable<int> ints)
{
if (!ints.Any()) {
return Enumerable.Empty<int>();
}
int pivot = ints.First();
IEnumerable<int> lt = ints.Where(i => i < pivot);
IEnumerable<int> gt = ints.Where(i => i > pivot);
return QuickSort(lt).Concat(new int[] { pivot }).Concat(QuickSort(gt));
}
Şimdi emin olmak için, bu hızlı bir nevi iyi bir uygulama olduğunu savunan değilim! Ancak lambda ifade akışı işlemi ile birlikte ifade gücünü büyük örneğidir.
Ve Java ile yapılabilir mi! Hatta kullanılmaz hale olmadan boş olup olmadığını akışı isteyemem.
CEVAP
Arka plan
Soru basit görünüyor olsa da, gerçek cevap mantıklı biraz bilgi gerektirir. Eğer sonuca atlamak istiyorsanız, aşağı doğru ilerleyin...
Karşılaştırma noktası Pick - Temel işlevsellik
Temel kavramlar kullanarak, C#'IEnumerable
s kavramı daha yakından istediğiniz 56 ** çok yaratabilen Java's Iterable
ile ilgilidir. IEnumerables
IEnumerators
oluşturun. Java Iterable
Iterators
oluşturun
Her kavram tarihi IEnumerable
Iterable
hem 'her' tarzı veri toplama üyeleri döngü içinde. izin vermek için temel bir motivasyon var, benzer, Onlar sadece daha fazla izin olarak bir basitleştirme, ve onlar da farklı gelişmeler ile bu aşamada geldi, ama önemli bir ortak özelliği ne olursa olsun.
Hadi karşılaştırmak özelliği: her iki dilde, eğer bir sınıf uygular IEnumerable
/Iterable
o zaman bu sınıf uygulamak gerekir en azından tek bir yöntem (C#, GetEnumerator
Java iterator()
). Her durumda, örnek (18*/Iterator
*) veri şimdiki ve sonraki üyeleri erişim sağlayan döndü. Bu özellik için-her dil sözdizimi kullanılır.
Karşılaştırma noktası Pick - işlevselliği Geliştirilmiş
IEnumerable
C# dili diğer özellikleri bir dizi sağlamak için uzatıldı (mostly related to Linq). Özellikler seçimleri, projeksiyonlar, toplamalardan, vb ekledi. Bu uzantıları, set-teoride kullanmak güçlü bir motivasyon, SQL ve İlişkisel Veritabanı kavramları benzer.
Java 8 de fonksiyonel programlama derecesi Dere ve Lambda kullanarak etkinleştirmek için eklenmiştir. Java 8 akışları öncelikle fonksiyonel programlama teori, ama motive olduğunu unutmayın. Ne olursa olsun, benzerlikler bir yeri vardır.
Bu da ikinci nokta. Geliştirmeleri C için yapılan# IEnumerable
konsepti için bir geliştirme olarak uygulanmıştır. Java olsa da, geliştirmeler yapıldı uygulanan yaratarak yeni bir temel kavramlarını Lambda ve Akarsular, ve sonra da oluşturma nispeten önemsiz bir şekilde dönüştürmek Iterators
Iterables
Akarsuları, ve vize-versa.
Bu yüzden, Java Stream kavramı için IEnumerable karşılaştırarak eksik. Java Dere ve Koleksiyonları kombine API karşılaştırmak gerekir.
Java, Akarsu İterables, ya Yineleyicisi olarak aynı değildir
Akışı sorunları kullanımına aynı şekilde çözmek için tasarlanmıştır:
- Kullanımına veri dizisi açıklayan bir yoludur.
- Veri akışı Dönüşümleri Bir dizi açıklayan bir yoludur.
Bir *ile 24* veri bir değeri olsun, işleyebilir ve başka bir veri değeri.
Akarsular, fonksiyonları bir dizi birlikte zincir, sonra akışı için bir giriş değeri besleme ve kombine sırası gelen çıktı değeri olsun. Not, Java açısından, her fonksiyonu Stream
tek bir örneği içinde saklanır. Akarsu API dönüşümü ifadelerin bir sıra zincir bir şekilde Stream
örnekleri bir dizi bağlantı sağlar.
Stream
konsepti tamamlamak için, veri kaynağı akışı ve akış tüketir terminal fonksiyon beslenmen gerek.
Yem akış değerleri bu şekilde aslında Iterable
ama Iterable
, bileşik bir fonksiyonu olduğunu bir kendisi değildir Stream
bir bölüm olabilir.
Stream
bir de tembel, sadece bir değer istemek için çalışır anlamda olması amaçlanmıştır.
Akarsuları: bunlar önemli varsayımlar ve özellikleri unutmayın
- Java
Stream
bir dönüşüm motoru, bir devlet, bir veri öğesi, başka bir devlet olmanın dönüştürüyor. - veri akışı düzeni veya pozisyon kavramı yok, sadece istenir ne dönüşüm var.
- akarsu çok kaynak, diğer akarsu, Kullanımına, İterables, Koleksiyonları da dahil olmak üzere, veri ile sağlanabilir
- olamaz "" akışı, böyle olurdu "dönüşümü yeniden programlama". Sıfırla Veri kaynağı sıfırlama ne istediğinizi muhtemelen değildir.
- mantıksal olarak sadece 1 veri öğesi yok 'uçuş' herhangi bir zamanda akış (akış paralel akış, hangi noktada olduğu sürece, başına iş parçacığı 1 öğe vardır.) Bu daha geçerli öğeler 'hazır' akışı temin edilecek veya akış toplayıcı toplama ve birden çok değer azaltmak için gerekebilir. var olan veri kaynağı bağımsızdır
- Akarsu ilişkisiz (sonsuz), yalnızca veri kaynağı, toplayıcı ya da sonsuz olabilir) ile sınırlı olabilir.
- Dere, bir akarsu filtreleme çıktı, başka bir akış. chainable vardır Ve bir akarsu tarafından dönüştürülmüş değerleri giriş sırayla farklı bir dönüşüm yapan bir akış sağlanabilir. Veriler, dönüştürülmüş haliyle yanındaki bir dere akar. Ve bir akış verileri müdahale çekin ve bir sonraki takmanız gerekmez.
C# Karşılaştırma
Ne zaman olduğunu düşündüğünüz bir Java Stream sadece bir kısmının kaynağı, akış ve toplama sistemi ve Dere ve Kullanımına sıklıkla kullanılan birlikte Koleksiyonları, o zaman hiç merak bu sıkı ilişki, aynı kavram olan neredeyse tüm gömülü tek IEnumerable
kavram C#.
IEnumerable parçaları (ve yakın ilişkili kavramlar) Java Yineleyici, İterable, Lambda, ve Akış kavramları bütün olarak görünür.
IEnumerable, ve vize-versa daha zor olan Java kavramları yapabileceğiniz küçük şeyler vardır.
Sonuç
- Burada tasarım problemi, diller arasındaki kavram eşleştirmede bir sorun yok.
- Akışları farklı bir şekilde sorunları çözmek
- Akarsu Java işlevselliği (şeyler yapmanın farklı bir yolu ekleyin, işlevsellik uzak almadan) ekleyin
Akarsu olarak sınıflandırmak için adil olan sorunları çözerken size daha fazla seçenek sunar ekleme 'güç arttırıcı', 'azaltma', 'götürmek', ya da 'kısıtlama'.
Neden Java Akışları kez kapalı?
Bu soruyu dere fonksiyon dizileri, veri değil çünkü yanlış. Akıntıyı besleyen veri kaynağına bağlı olarak, veri kaynağı sıfırlama, ve aynı, ya da farklı bir akış besleyebilirsiniz.
'Yürütme boru hattına birçok kez istediğimiz gibi, Java stream 'sadece bir kez. yinelenen olarak idam edilebilir s IEnumerable, aksine C#
Stream
IEnumerable
bir karşılaştırma yanlış olur. IEnumerable
istediğiniz kadar birçok kez idam, olabilir demek için kullanıyorsunuz kapsamında en iyi olarak birçok kez istediğiniz gibi yinelenen olabilir Iterables
Java ile karşılaştırılır. Stream
IEnumerable
kavramının bir alt kümesi ve veri kaynakları, ve bu nedenle bu alt değil temsil bir Java olur. yeniden
Ölümcül bir operasyon için herhangi bir çağrı akışı, kullanılmaz hale kapatır. ''Güç bir sürü alır. özelliği bu
İlk ifade doğru, bir bakıma. 'Güç' ifadesi değil. alır götürür Hala İEnumerables Akarsu karşılaştırma. Akışında terminal operasyon bir 'break' döngü. bir fıkra gibi. Her zaman eğer isterseniz başka bir akış var, özgürsünüz, ve yeniden sağlayabilir verileri gerekir. Eğer IEnumerable
gibi Iterable
, bu ifade için olduğunu düşünüyorsanız, tekrar, Java, sorun yok.
Bu teknik değil nedenini tahmin edebiliyorum. Bu garip bir kısıtlama arkasında tasarım konuları nelerdi?
Sebebi teknik ve bir Dere ne bir alt kümesi gibi basit bir sebepten. Stream alt kaynağı, akış Sıfırla bu yüzden veri kaynağını kontrol etmez. Bu bağlamda, bu çok garip değil.
Örnek QuickSort
Quicksort örnek imza:
IEnumerable<int> QuickSort(IEnumerable<int> ints)
Veri kaynağı olarak 43* *giriş şımart:
IEnumerable<int> lt = ints.Where(i => i < pivot);
Ayrıca, dönüş değeri veri kaynağı olan, IEnumerable
de,, ve bu Tür bir operasyon olduğu için, bu arz sırası önemlidir. Eğer düşündüğünüz Java Iterable
sınıf için uygun bir maç için bu, özellikle List
uzmanlık Iterable
beri listesidir kaynağı veri olan bir garanti sipariş veya yineleme, sonra eşdeğer Java kodu için kod olabilir:
Stream<Integer> quickSort(List<Integer> ints) {
// Using a stream to access the data, instead of the simpler ints.isEmpty()
if (!ints.stream().findAny().isPresent()) {
return Stream.of();
}
// treating the ints as a data collection, just like the C#
final Integer pivot = ints.get(0);
// Using streams to get the two partitions
List<Integer> lt = ints.stream().filter(i -> i < pivot).collect(Collectors.toList());
List<Integer> gt = ints.stream().filter(i -> i > pivot).collect(Collectors.toList());
return Stream.concat(Stream.concat(quickSort(lt), Stream.of(pivot)),quickSort(gt));
}
Bir hata yeniden var olan, sıralama değerleri düzgün bir şekilde işlemek çoğaltmak değil, bir 'benzersiz bir değer' tür. not yok
Ayrıca not nasıl Java kodu kullanır, veri kaynağı (List
) ve akış kavramları farklı nokta ve C# bu iki 'kişilikleri' ifade edebilir sadece IEnumerable
. Ayrıca, ancak ben kullanmak List
taban türü, kullanılabilir daha genel Collection
ve bir küçük yineleyici-Akış dönüşüm, yapardım eskiden daha genel Iterable
Neden char[] şifreler için Dize Java t...
Neden belirli Unicode karakterler içer...
Neden Java geçici değişkenler var mı?...
Neden Java Vector sınıfı eski veya kul...
Neden Java statik olarak bir sınıf bil...