Saya bertanya-tanya mengapa Iterable
antarmuka tidak menyediakan stream()
dan parallelStream()
metode. Pertimbangkan kelas berikut:
public class Hand implements Iterable<Card> {
private final List<Card> list = new ArrayList<>();
private final int capacity;
//...
@Override
public Iterator<Card> iterator() {
return list.iterator();
}
}
Ini adalah implementasi dari Tangan karena Anda dapat memiliki kartu di tangan Anda saat memainkan Permainan Kartu Perdagangan.
Pada dasarnya itu membungkus List<Card>
, memastikan kapasitas maksimum dan menawarkan beberapa fitur berguna lainnya. Lebih baik menerapkannya secara langsung sebagai List<Card>
.
Sekarang, untuk kenyamanan saya pikir akan lebih baik untuk diimplementasikan Iterable<Card>
, sehingga Anda dapat menggunakan loop for-ditingkatkan jika Anda ingin mengulanginya. ( Hand
Kelas saya juga menyediakan get(int index)
metode, oleh karena Iterable<Card>
itu dibenarkan menurut pendapat saya.)
The Iterable
antarmuka menyediakan berikut (ditinggalkan javadoc):
public interface Iterable<T> {
Iterator<T> iterator();
default void forEach(Consumer<? super T> action) {
Objects.requireNonNull(action);
for (T t : this) {
action.accept(t);
}
}
default Spliterator<T> spliterator() {
return Spliterators.spliteratorUnknownSize(iterator(), 0);
}
}
Sekarang Anda dapat memperoleh aliran dengan:
Stream<Hand> stream = StreamSupport.stream(hand.spliterator(), false);
Jadi pertanyaan sebenarnya:
- Mengapa
Iterable<T>
tidak menyediakan metode default yang menerapkanstream()
danparallelStream()
, saya tidak melihat apa pun yang membuat ini tidak mungkin atau tidak diinginkan?
Pertanyaan terkait yang saya temukan adalah sebagai berikut: Mengapa Stream <T> tidak mengimplementasikan Iterable <T>?
Yang anehnya cukup menyarankan untuk melakukannya agak sebaliknya.
sumber
break;
melakukan iterasi? (Ok,Stream.findFirst()
mungkin solusi, tapi itu mungkin tidak memenuhi semua kebutuhan ...)Jawaban:
Ini bukan kelalaian; ada diskusi terperinci tentang daftar EG pada Juni 2013.
Diskusi definitif dari Kelompok Pakar berakar di utas ini .
Sementara itu tampak "jelas" (bahkan untuk Kelompok Ahli, pada awalnya) yang
stream()
tampaknya masuk akalIterable
, fakta yangIterable
begitu umum menjadi masalah, karena tanda tangan yang jelas:tidak selalu seperti yang Anda inginkan. Beberapa hal yang
Iterable<Integer>
lebih suka metode aliran mereka mengembalikanIntStream
, misalnya. Tetapi menempatkanstream()
metode ini setinggi-tingginya dalam hierarki akan membuat itu tidak mungkin. Jadi sebagai gantinya, kami membuatnya sangat mudah untuk membuatStream
dariIterable
, dengan menyediakanspliterator()
metode. Implementasistream()
dalamCollection
hanyalah:Setiap klien dapat memperoleh aliran yang mereka inginkan dari
Iterable
dengan:Pada akhirnya kami menyimpulkan bahwa menambahkan
stream()
untukIterable
akan menjadi suatu kesalahan.sumber
Iterable<Integer>
(saya pikir Anda bicarakan?) Ingin mengembalikan sebuahIntStream
. Apakah iterable maka tidak suka menjadiPrimitiveIterator.OfInt
? Atau mungkin maksud Anda usecase lain?Stream.of(Iterable)
, yang setidaknya akan membuat metode ini dapat ditemukan dengan membaca dokumentasi API - sebagai seseorang yang tidak pernah benar-benar bekerja dengan internal Streams yang tidak pernah saya lakukan. bahkan tampak diStreamSupport
, yang dijelaskan dalam dokumentasi menyediakan "operasi tingkat rendah" yang "sebagian besar untuk penulis perpustakaan".Saya melakukan penyelidikan di beberapa milis proyek lambda dan saya pikir saya menemukan beberapa diskusi yang menarik.
Sejauh ini saya belum menemukan penjelasan yang memuaskan. Setelah membaca semua ini, saya menyimpulkan bahwa itu hanyalah kelalaian. Tetapi Anda dapat melihat di sini bahwa itu telah dibahas beberapa kali selama bertahun-tahun selama desain API.
Lambda Libs Spec Ahli
Saya menemukan diskusi tentang ini di mailing list Lambda Libs Spec Experts :
Di bawah Iterable / Iterator.stream () Sam Pullara berkata:
Dan kemudian Brian Goetz merespons :
Dan kemudian
Diskusi Sebelumnya di Mailing List Lambda
Ini mungkin bukan jawaban yang Anda cari tetapi dalam milis Project Lambda ini dibahas secara singkat. Mungkin ini membantu mendorong diskusi yang lebih luas tentang masalah ini.
Dalam kata-kata Brian Goetz di bawah Streams from Iterable :
Kontradiksi?
Meskipun, sepertinya diskusi didasarkan pada perubahan yang dilakukan Kelompok Pakar terhadap desain awal Streams yang awalnya didasarkan pada iterator.
Meski begitu, menarik untuk diperhatikan bahwa di antarmuka seperti Collection, metode stream didefinisikan sebagai:
Kode yang persis sama dengan yang digunakan dalam antarmuka Iterable.
Jadi, inilah mengapa saya mengatakan jawaban ini mungkin tidak memuaskan, tetapi masih menarik untuk dibahas.
Bukti Refactoring
Melanjutkan analisis di milis, sepertinya metode splitIterator pada awalnya berada di antarmuka Collection, dan pada beberapa titik di 2013 mereka memindahkannya ke Iterable.
Tarik splitIterator dari Koleksi ke Iterable .
Kesimpulan / Teori?
Maka kemungkinannya adalah bahwa kurangnya metode di Iterable hanya kelalaian, karena sepertinya mereka seharusnya telah memindahkan metode aliran juga ketika mereka memindahkan splitIterator dari Collection ke Iterable.
Jika ada alasan lain, itu tidak jelas. Ada yang punya teori lain?
sumber
spliterator()
dariIterable
, maka semua masalah ada tetap, dan Anda dapat sepele menerapkanstream()
danparallelStream()
..Jika Anda tahu ukuran yang bisa Anda gunakan
java.util.Collection
yang menyediakanstream()
metode ini:Lalu:
Saya menghadapi masalah yang sama dan terkejut bahwa
Iterable
implementasi saya dapat dengan mudah diperluas keAbstractCollection
implementasi hanya dengan menambahkansize()
metode (untungnya saya memiliki ukuran koleksi :-)Anda juga harus mempertimbangkan untuk mengganti
Spliterator<E> spliterator()
.sumber