Під час проходження способів перетворення примітивних масивів у Streams, я виявив, що char[]
вони не підтримуються, тоді як підтримуються інші типи примітивних масивів. Якась конкретна причина залишати їх у потоці?
Під час проходження способів перетворення примітивних масивів у Streams, я виявив, що char[]
вони не підтримуються, тоді як підтримуються інші типи примітивних масивів. Якась конкретна причина залишати їх у потоці?
Відповіді:
Як сказав Еран, це не єдиний зниклий безвісти.
A BooleanStream
було б марним, a ByteStream
(якщо воно існувало) можна обробляти як InputStream
або перетворювати на IntStream
(як можна short
), і float
можна обробляти як a DoubleStream
.
Оскільки char
не в змозі представити всіх символів у будь-якому випадку (див. Зв'язане), це було б трохи застарілим потоком. Хоча більшості людей так чи інакше доводиться мати справу з кодовими точками, це може здатися дивним. Я маю на увазі, що ви використовуєте, String.charAt()
не замислюючись, «це насправді не працює у всіх випадках».
Тож деякі речі були залишені, оскільки вони не вважалися такими важливими. Як сказав JB Nizet у пов'язаному питанні :
Дизайнери явно вирішили уникнути вибуху класів і методів, обмеживши примітивні потоки на 3 типи, оскільки інші типи (char, short, float) можуть бути представлені їх більшим еквівалентом (int, double) без будь-якого значного покарання.
Причина BooleanStream
була б марною, оскільки у вас є лише 2 значення, і це дуже обмежує операції. Математичних операцій робити не потрібно, і як часто ви працюєте з великою кількістю булевих значень?
BooleanStream
було б марно": чому?
reduce(Boolean::logicalAnd)
або reduce(Boolean::logicalOr)
на boolean[]
? В кінці кінців, методи logicalAnd
і logicalOr
були додані в Java 8, так що я можу зробити ці операції редукції Stream<Boolean>
... До речі, ви можете передавати більше char[]
так легко , як CharBuffer.wrap(array).chars()
і CharBuffer.wrap(array).codePoints()
, в залежності від яких семантичних ви віддаєте перевагу.
Boolean::logicalAnd
існує, він не обов'язково гарантує існування BooleanStream
. Зрештою, їх можна використовувати в ситуаціях без потоку лямбда. Я можу собі уявити , що хтось - то хоче зробити reduce(Boolean::logicalAnd)
, але ні в якому разі не кому - потрібно зробити це.
while (i < limit)
, але ні в якому разі нікому це не потрібно робити [над використанням інструкцій зі складання гілок і стрибків]"
<Primitive>Stream
для кожного примітивного типу, є те, що він занадто сильно роздує API. Правильне запитання, яке потрібно задати - "чому взагалі існує IntStream
?" і прикрою відповіддю є те, що система типу Java недостатньо розроблена, щоб виражати Stream<int>
без усіх витрат на використання продуктивності Integer
. Якби у Java були типи значень, які можна було б виділити в стек або вставити безпосередньо в рядок в інші структури даних, не було б такої потреби в іншомуStream<T>
Звичайно, відповідь « адже саме так вирішили дизайнери ». Немає технічної причини, чому CharStream
не могло б існувати.
Якщо ви хочете виправдання, вам зазвичай потрібно повернути список розсилки OpenJDK *. Документація JDK не має звичаю пояснювати, чому все так і є.
Хтось запитав
Використовувати IntStream для представлення потоку char / byte трохи незручно. Чи слід також додати CharStream та ByteStream?
Відповідь Брайана Геца (Java Language Architect) говорить
Коротка відповідь: ні.
Не варто більше 100K + слід JDK для цих форм, які використовуються майже ніколи. І якби ми додали ці, хтось вимагав би коротких, плаваючих або булевих.
По-іншому, якби люди наполягали на тому, що ми маємо всі примітивні спеціалізації, у нас не було б примітивних спеціалізацій. Що було б гірше, ніж статус-кво.
Те ж він говорить і в інших місцях
Якщо ви хочете розібратися з ними як символи, ви можете їх легко замінити на символи досить легко. Не здається достатньо важливим випадком використання, щоб мати цілий набір потоків. (Те саме з Короткий, Байт, Поплавок).
TL; DR: Не варто витрат на обслуговування.
* Якщо вам цікаво, я використовував запит google
site:http://mail.openjdk.java.net/ charstream
100K+ of JDK footprint
?
Це не лише char
масиви, які не підтримуються.
Існує лише 3 типи примітивних потоків - IntStream
, LongStream
і DoubleStream
.
В результаті Arrays
є методи, які перетворюють int[]
, long[]
і double[]
у відповідні примітивні потоки.
Там немає відповідних методів boolean[]
, byte[]
, short[]
, char[]
і float[]
, так як ці примітивні типів мають відповідні примітивні потоки.
char
є залежною частиною String
- зберігання значень UTF-16. Символ Unicode, кодова точка , іноді є сурогатною парою знаків. Отже, будь-яке просте рішення з символами охоплює лише частину домену Unicode.
Був час, який char
мав своє право бути публічним типом. Але в наш час, краще використовувати кодові точки , IntStream
. Потік чарівності не міг прямо впоратися із сурогатними парами.
Інша більш прозаїчна причина полягає в тому, що модель "процесора" JVM використовує int
як найменший "регістр", зберігаючи булеві, байтові, шорти, а також символи в такому розмірі місця для зберігання. Щоб не обов'язково роздувати класи java, один утримався від усіх можливих варіантів копіювання.
В майбутньому можна очікувати, що примітивні типи, які можуть функціонувати як параметри загального типу, забезпечують a List<int>
. Тоді ми можемо побачити Stream<char>
.
На даний момент краще уникати char
, а можливо, використовувати java.text.Normalizer
для унікальної канонічної форми точок коду / рядків Unicode.