Mengapa char [] satu-satunya array yang tidak didukung oleh Arrays.stream ()?
43
Sementara melalui cara-cara mengubah array primitif ke Streams, saya menemukan bahwa char[]tidak didukung sementara tipe array primitif lainnya didukung. Adakah alasan khusus untuk meninggalkan mereka di arus?
Seperti yang dikatakan Eran, itu bukan satu-satunya yang hilang.
A BooleanStreamtidak akan berguna, a ByteStream(jika ada) dapat ditangani sebagai InputStreamatau diubah menjadi IntStream(as can short), dan floatdapat ditangani sebagai a DoubleStream.
Karena chartidak dapat mewakili semua karakter (lihat ditautkan), itu akan menjadi sedikit aliran warisan. Meskipun kebanyakan orang tidak harus berurusan dengan codepoint, jadi itu bisa terasa aneh. Maksud saya Anda menggunakan String.charAt()tanpa berpikir "ini sebenarnya tidak bekerja dalam semua kasus".
Jadi beberapa hal ditinggalkan karena tidak dianggap penting. Seperti yang dikatakan oleh JB Nizet dalam pertanyaan terkait :
Para desainer secara eksplisit memilih untuk menghindari ledakan kelas dan metode dengan membatasi aliran primitif menjadi 3 jenis, karena jenis lainnya (char, short, float) dapat diwakili oleh padanannya yang lebih besar (int, dobel) tanpa penalti kinerja yang signifikan.
Alasannya BooleanStreamakan sia-sia, adalah karena Anda hanya memiliki 2 nilai dan itu membatasi banyak operasi. Tidak ada operasi matematika untuk dilakukan, dan seberapa sering Anda bekerja dengan banyak nilai boolean?
Apakah benar-benar tidak masuk akal untuk mengasumsikan seseorang perlu melakukan, misalnya reduce(Boolean::logicalAnd)atau reduce(Boolean::logicalOr), pada boolean[]? Lagi pula, metode logicalAnddan logicalOrtelah ditambahkan di Java 8, jadi saya bisa melakukan operasi pengurangan ini dari Stream<Boolean>... Omong-omong, Anda dapat streaming melalui char[]semudah CharBuffer.wrap(array).chars()atau CharBuffer.wrap(array).codePoints(), tergantung semantik yang Anda inginkan.
Holger
2
@ Holger hanya karena Boolean::logicalAndada, itu tidak selalu menjamin adanya a BooleanStream. Bagaimanapun, itu dapat digunakan dalam situasi lambda non-stream. Saya dapat membayangkan bahwa seseorang ingin melakukannya reduce(Boolean::logicalAnd), tetapi tidak ada orang yang perlu melakukannya.
Kayaman
4
Saya tidak melihat argumen apa yang Anda coba buat. Dalam bentuknya yang ekstrem: "Saya dapat membayangkan bahwa seseorang ingin melakukannya while (i < limit), tetapi tidak ada orang yang perlu melakukannya [menggunakan instruksi cabang dan lompat perakitan]"
Alexander - Reinstate Monica
11
Sepertinya saya satu-satunya alasan tidak ada <Primitive>Streamuntuk setiap jenis primitif adalah karena itu akan terlalu banyak mengasapi API. Pertanyaan yang benar untuk ditanyakan adalah "mengapa ada IntStream?" dan jawaban yang tidak menguntungkan adalah karena sistem tipe Java tidak cukup untuk mengekspresikan Stream<int>tanpa semua biaya kinerja menggunakan Integer. Jika Java memiliki tipe nilai, yang dapat dialokasikan pada stack atau menanamkan secara langsung in-line dalam struktur data lain, tidak akan ada kebutuhan seperti itu untuk apa pun selainStream<T>
Alexander - Reinstate Monica
32
Tentu saja, jawabannya adalah " karena itulah yang diputuskan oleh desainer ". Tidak ada alasan teknis mengapa CharStreamtidak ada.
Jika Anda ingin pembenaran, Anda biasanya perlu mengaktifkan milis OpenJDK *. Dokumentasi JDK bukanlah kebiasaan untuk membenarkan mengapa ada sesuatu yang menyebabkannya.
Seseorang bertanya
Menggunakan IntStream untuk mewakili aliran char / byte sedikit merepotkan. Haruskah kita menambahkan CharStream dan ByteStream juga?
Jawaban dari Brian Goetz (Arsitek Bahasa Jawa) mengatakan
Jawaban singkat: tidak.
Tidak perlu lagi 100K + jejak JDK untuk masing-masing bentuk yang hampir tidak pernah digunakan. Dan jika kita menambahkannya, seseorang akan meminta short, float, atau boolean.
Dengan kata lain, jika orang bersikeras kita memiliki semua spesialisasi primitif, kita tidak akan memiliki spesialisasi primitif. Yang akan lebih buruk daripada status quo.
Jika Anda ingin mengatasinya sebagai chars, Anda dapat dengan mudah menurunkannya menjadi chars. Tampaknya bukan kasus penggunaan yang cukup penting untuk memiliki rangkaian aliran nother keseluruhan. (Sama dengan Short, Byte, Float).
Bisakah seseorang menjelaskan apa yang mereka maksud 100K+ of JDK footprint?
yassin
3
@Yassin Seseorang harus menulis kode. Dia memperkirakan bahwa setiap spesialisasi aliran adalah lebih dari 100.000 baris kode
Michael
3
@BulgarSadykov Pertanyaan semacam itu tentang " mengapa X seperti Y " sering ditutup sebagai berbasis opini karena tidak mungkin untuk membaca pikiran penulis asli dan, kecuali jika mereka muncul, yang akan Anda dapatkan hanyalah dugaan. Jika saya bertanya "bagaimana cara mengirim permintaan POST dengan klien HTTP Apache?", Siapa pun yang akrab dengan perpustakaan dapat menjawabnya. Mengapa perpustakaan dirancang seperti itu biasanya tidak mungkin dijawab. Satu-satunya alasan kami dapat menjawab ini benar-benar karena ada catatan publik percakapan mereka. Itulah yang saya coba lakukan dengan kalimat pertama.
Michael
2
@BulgarSadykov juga mengingatkan ini, menyebutkan blog Eric Lippert, tentang C #, tetapi pada topik "mengapa fitur Foo tidak diimplementasikan dalam bahasa" stackoverflow.com/a/5588850/479251
Pac0
2
@BulgarSadykov Dengan hormat tidak setuju. Sekali lagi, saya ulangi contoh pertanyaan saya tentang " bagaimana cara mengirim permintaan POST dengan klien HTTP Apache? ". Jawaban atas pertanyaan itu jelas tidak dimulai dengan " karena itulah yang diputuskan oleh perancang ". Saya tidak mengubah kata-katanya, maaf.
Michael
7
Bukan hanya chararray yang tidak didukung.
Hanya ada 3 jenis aliran primitif - IntStream, LongStreamdan DoubleStream.
Akibatnya, Arraysmemiliki metode yang mengkonversi int[], long[]dan double[]ke aliran primitif yang sesuai.
Tidak ada metode yang sesuai untuk boolean[], byte[], short[], char[]dan float[], karena ini jenis primitif telah ada sesuai primitif sungai.
"Karena tipe primitif ini tidak memiliki aliran primitif yang sesuai." Maka pertanyaan selanjutnya adalah "mengapa"?
Federico klez Culloca
7
@FedericoklezCulloca pertanyaan lanjutan dijawab di sini
Eran
6
charadalah bagian dependen dari String- menyimpan nilai UTF-16. Simbol Unicode, titik kode , terkadang merupakan pasangan pengganti karakter. Jadi setiap solusi sederhana dengan karakter hanya mencakup sebagian dari domain Unicode.
Ada waktu yang charmemiliki hak sendiri untuk menjadi tipe publik. Tetapi saat ini lebih baik menggunakan poin kode , sebuah IntStream. Aliran arang tidak bisa langsung menangani pasangan pengganti.
Alasan lain yang lebih umum adalah bahwa model "prosesor" JVM menggunakan int"register" terkecil, menjaga boolean, byte, celana pendek dan juga karakter di lokasi penyimpanan berukuran int. Untuk tidak selalu mengasapi kelas java, satu menahan diri dari semua varian salinan yang mungkin.
Di masa depan yang jauh mungkin mengharapkan tipe primitif diizinkan berfungsi sebagai parameter tipe generik, memberikan a List<int>. Maka kita mungkin melihat Stream<char>.
Untuk saat ini sebaiknya hindari char, dan mungkin gunakan java.text.Normalizeruntuk bentuk kanonik unik dari poin kode / string Unicode.
Jawaban:
Seperti yang dikatakan Eran, itu bukan satu-satunya yang hilang.
A
BooleanStream
tidak akan berguna, aByteStream
(jika ada) dapat ditangani sebagaiInputStream
atau diubah menjadiIntStream
(as canshort
), danfloat
dapat ditangani sebagai aDoubleStream
.Karena
char
tidak dapat mewakili semua karakter (lihat ditautkan), itu akan menjadi sedikit aliran warisan. Meskipun kebanyakan orang tidak harus berurusan dengan codepoint, jadi itu bisa terasa aneh. Maksud saya Anda menggunakanString.charAt()
tanpa berpikir "ini sebenarnya tidak bekerja dalam semua kasus".Jadi beberapa hal ditinggalkan karena tidak dianggap penting. Seperti yang dikatakan oleh JB Nizet dalam pertanyaan terkait :
Alasannya
BooleanStream
akan sia-sia, adalah karena Anda hanya memiliki 2 nilai dan itu membatasi banyak operasi. Tidak ada operasi matematika untuk dilakukan, dan seberapa sering Anda bekerja dengan banyak nilai boolean?sumber
BooleanStream
akan sia-sia": mengapa?reduce(Boolean::logicalAnd)
ataureduce(Boolean::logicalOr)
, padaboolean[]
? Lagi pula, metodelogicalAnd
danlogicalOr
telah ditambahkan di Java 8, jadi saya bisa melakukan operasi pengurangan ini dariStream<Boolean>
... Omong-omong, Anda dapat streaming melaluichar[]
semudahCharBuffer.wrap(array).chars()
atauCharBuffer.wrap(array).codePoints()
, tergantung semantik yang Anda inginkan.Boolean::logicalAnd
ada, itu tidak selalu menjamin adanya aBooleanStream
. Bagaimanapun, itu dapat digunakan dalam situasi lambda non-stream. Saya dapat membayangkan bahwa seseorang ingin melakukannyareduce(Boolean::logicalAnd)
, tetapi tidak ada orang yang perlu melakukannya.while (i < limit)
, tetapi tidak ada orang yang perlu melakukannya [menggunakan instruksi cabang dan lompat perakitan]"<Primitive>Stream
untuk setiap jenis primitif adalah karena itu akan terlalu banyak mengasapi API. Pertanyaan yang benar untuk ditanyakan adalah "mengapa adaIntStream
?" dan jawaban yang tidak menguntungkan adalah karena sistem tipe Java tidak cukup untuk mengekspresikanStream<int>
tanpa semua biaya kinerja menggunakanInteger
. Jika Java memiliki tipe nilai, yang dapat dialokasikan pada stack atau menanamkan secara langsung in-line dalam struktur data lain, tidak akan ada kebutuhan seperti itu untuk apa pun selainStream<T>
Tentu saja, jawabannya adalah " karena itulah yang diputuskan oleh desainer ". Tidak ada alasan teknis mengapa
CharStream
tidak ada.Jika Anda ingin pembenaran, Anda biasanya perlu mengaktifkan milis OpenJDK *. Dokumentasi JDK bukanlah kebiasaan untuk membenarkan mengapa ada sesuatu yang menyebabkannya.
Seseorang bertanya
Jawaban dari Brian Goetz (Arsitek Bahasa Jawa) mengatakan
Sumber
Dia juga mengatakan hal yang sama di tempat lain
Sumber
TL; DR: Tidak sebanding dengan biaya perawatan.
* Jika Anda penasaran, kueri google yang saya gunakan adalah
sumber
100K+ of JDK footprint
?Bukan hanya
char
array yang tidak didukung.Hanya ada 3 jenis aliran primitif -
IntStream
,LongStream
danDoubleStream
.Akibatnya,
Arrays
memiliki metode yang mengkonversiint[]
,long[]
dandouble[]
ke aliran primitif yang sesuai.Tidak ada metode yang sesuai untuk
boolean[]
,byte[]
,short[]
,char[]
danfloat[]
, karena ini jenis primitif telah ada sesuai primitif sungai.sumber
char
adalah bagian dependen dariString
- menyimpan nilai UTF-16. Simbol Unicode, titik kode , terkadang merupakan pasangan pengganti karakter. Jadi setiap solusi sederhana dengan karakter hanya mencakup sebagian dari domain Unicode.Ada waktu yang
char
memiliki hak sendiri untuk menjadi tipe publik. Tetapi saat ini lebih baik menggunakan poin kode , sebuahIntStream
. Aliran arang tidak bisa langsung menangani pasangan pengganti.Alasan lain yang lebih umum adalah bahwa model "prosesor" JVM menggunakan
int
"register" terkecil, menjaga boolean, byte, celana pendek dan juga karakter di lokasi penyimpanan berukuran int. Untuk tidak selalu mengasapi kelas java, satu menahan diri dari semua varian salinan yang mungkin.Di masa depan yang jauh mungkin mengharapkan tipe primitif diizinkan berfungsi sebagai parameter tipe generik, memberikan a
List<int>
. Maka kita mungkin melihatStream<char>
.Untuk saat ini sebaiknya hindari
char
, dan mungkin gunakanjava.text.Normalizer
untuk bentuk kanonik unik dari poin kode / string Unicode.sumber