Di Java 8 kita memiliki Stream kelas <T> , yang anehnya memiliki metode
Iterator<T> iterator()
Jadi Anda akan mengharapkannya untuk mengimplementasikan antarmuka Iterable <T> , yang membutuhkan metode ini, tapi bukan itu masalahnya.
Ketika saya ingin mengulangi Stream menggunakan loop foreach, saya harus melakukan sesuatu seperti
public static Iterable<T> getIterable(Stream<T> s) {
return new Iterable<T> {
@Override
public Iterator<T> iterator() {
return s.iterator();
}
};
}
for (T element : getIterable(s)) { ... }
Apakah saya melewatkan sesuatu di sini?
java
java-8
java-stream
iterable
berkeliaran
sumber
sumber
Stream
ke API lawas yang diharapkanIterable
getIterable()
menjadireturn s::iterator;
for (T element : stream::iterator)
, jadi saya masih lebih suka jika Stream juga menerapkanIterable
atau metodetoIterable()
.Jawaban:
Orang-orang sudah menanyakan hal yang sama di milis ☺. Alasan utamanya adalah Iterable juga memiliki semantik yang dapat diulang kembali, sedangkan Stream tidak.
sumber
Iterable
tentang apakahiterator
harus selalu atau tidak dapat dihubungi berkali-kali. Itu sesuatu yang harus mereka masukkan ke sana. Ini tampaknya lebih merupakan praktik standar daripada spesifikasi formal.Untuk mengonversi a
Stream
menjadiIterable
, Anda dapat melakukannyaUntuk meneruskan
Stream
metode yang diharapkanIterable
,secara sederhana
namun mungkin terlihat lucu; mungkin lebih baik sedikit lebih eksplisit
sumber
for(X x : (Iterable<X>)stream::iterator)
, meskipun terlihat jelek. Sungguh, seluruh situasi itu tidak masuk akal.IntStream.range(0,N).forEach(System.out::println)
stream::iterator
danstream.iterator()
, yang membuat yang pertama dapat diterimaIterable
tetapi bukan yang kedua?Iterable
adalah antarmuka fungsional, jadi melewati fungsi yang mengimplementasikannya sudah cukup.Saya ingin menunjukkan bahwa
StreamEx
tidak mengimplementasikanIterable
(danStream
), serta sejumlah fungsi luar biasa lainnya yang hilangStream
.sumber
Anda dapat menggunakan Stream dalam satu
for
loop sebagai berikut:(Jalankan cuplikan ini di sini )
(Ini menggunakan pemeran antarmuka fungsional Java 8.)
(Ini tercakup dalam beberapa komentar di atas (misalnya Aleksandr Dubinsky ), tetapi saya ingin menariknya ke dalam jawaban untuk membuatnya lebih terlihat.)
sumber
kennytm menjelaskan mengapa tidak aman untuk memperlakukan
Stream
sebagaiIterable
, dan Zhong Yu menawarkan solusi yang mengizinkan penggunaanStream
sebagaiIterable
, meskipun dengan cara yang tidak aman. Dimungkinkan untuk mendapatkan yang terbaik dari kedua dunia: yang dapat digunakan kembaliIterable
dariStream
yang memenuhi semua jaminan yang dibuat olehIterable
spesifikasi.Catatan:
SomeType
bukan parameter tipe di sini - Anda harus menggantinya dengan tipe yang tepat (misalnya,String
) atau menggunakan refleksiAda satu kelemahan utama:
Manfaat iterasi malas akan hilang. Jika Anda berencana untuk segera beralih ke semua nilai di utas saat ini, setiap overhead akan diabaikan. Namun, jika Anda berencana untuk mengulangi hanya sebagian atau di utas yang berbeda, iterasi segera dan lengkap ini dapat memiliki konsekuensi yang tidak diinginkan.
Keuntungan besar, tentu saja, adalah Anda dapat menggunakan kembali
Iterable
, sedangkan(Iterable<SomeType>) stream::iterator
hanya akan mengizinkan penggunaan tunggal. Jika kode penerima akan mengulangi koleksi beberapa kali, ini tidak hanya diperlukan, tetapi kemungkinan bermanfaat untuk kinerja.sumber
Stream.toArray()
mengembalikan array, bukan sebuahIterable
, jadi kode ini masih tidak dapat dikompilasi. tapi itu mungkin bug dalam gerhana, karena IntelliJ tampaknya mengkompilasinyaStream
tidak menerapkanIterable
. Pemahaman umum tentangIterable
apa pun yang dapat diulangi, seringkali berulang kali.Stream
mungkin tidak dapat diputar ulang.Satu-satunya solusi yang dapat saya pikirkan, di mana iterable berdasarkan aliran adalah replayable juga, adalah menciptakan kembali aliran. Saya menggunakan di
Supplier
bawah ini untuk membuat contoh baru aliran, setiap kali iterator baru dibuat.sumber
Jika Anda tidak keberatan menggunakan perpustakaan pihak ketiga cyclops-react menentukan Stream yang mengimplementasikan Stream dan Iterable dan juga dapat diputar ulang (memecahkan masalah yang dijelaskan kennytm ).
atau :-
[Pengungkapan Saya adalah pengembang utama cyclops-react]
sumber
Tidak sempurna, tetapi akan berhasil:
Tidak sempurna karena itu akan mengambil semua item dari aliran dan memasukkannya ke dalam itu
List
, yang bukan apaIterable
danStream
tentang. Mereka seharusnya malas .sumber
Anda dapat mengulangi semua file dalam folder menggunakan
Stream<Path>
seperti ini:sumber