Чому char [] єдиний масив не підтримується Arrays.stream ()?


43

Під час проходження способів перетворення примітивних масивів у Streams, я виявив, що char[]вони не підтримуються, тоді як підтримуються інші типи примітивних масивів. Якась конкретна причина залишати їх у потоці?


3
stackoverflow.com/questions/22435833/… Ця тема IMO вирішує пов'язане питання
Марк Брамник

Відповіді:


31

Як сказав Еран, це не єдиний зниклий безвісти.

A BooleanStreamбуло б марним, a ByteStream(якщо воно існувало) можна обробляти як InputStreamабо перетворювати на IntStream(як можна short), і floatможна обробляти як a DoubleStream.

Оскільки charне в змозі представити всіх символів у будь-якому випадку (див. Зв'язане), це було б трохи застарілим потоком. Хоча більшості людей так чи інакше доводиться мати справу з кодовими точками, це може здатися дивним. Я маю на увазі, що ви використовуєте, String.charAt()не замислюючись, «це насправді не працює у всіх випадках».

Тож деякі речі були залишені, оскільки вони не вважалися такими важливими. Як сказав JB Nizet у пов'язаному питанні :

Дизайнери явно вирішили уникнути вибуху класів і методів, обмеживши примітивні потоки на 3 типи, оскільки інші типи (char, short, float) можуть бути представлені їх більшим еквівалентом (int, double) без будь-якого значного покарання.

Причина BooleanStreamбула б марною, оскільки у вас є лише 2 значення, і це дуже обмежує операції. Математичних операцій робити не потрібно, і як часто ви працюєте з великою кількістю булевих значень?


7
BooleanStreamбуло б марно": чому?
glglgl

12
Це дійсно нерозумно припускати, що хтось може це зробити, наприклад, reduce(Boolean::logicalAnd)або reduce(Boolean::logicalOr)на boolean[]? В кінці кінців, методи logicalAndі logicalOrбули додані в Java 8, так що я можу зробити ці операції редукції Stream<Boolean>... До речі, ви можете передавати більше char[]так легко , як CharBuffer.wrap(array).chars()і CharBuffer.wrap(array).codePoints(), в залежності від яких семантичних ви віддаєте перевагу.
Холгер

2
@Holger тільки тому, що Boolean::logicalAndіснує, він не обов'язково гарантує існування BooleanStream. Зрештою, їх можна використовувати в ситуаціях без потоку лямбда. Я можу собі уявити , що хтось - то хоче зробити reduce(Boolean::logicalAnd), але ні в якому разі не кому - потрібно зробити це.
Каяман

4
Я не бачу, який аргумент ви намагаєтесь зробити. У його крайній формі: "Я можу уявити, що хтось хотів би це зробити while (i < limit), але ні в якому разі нікому це не потрібно робити [над використанням інструкцій зі складання гілок і стрибків]"
Олександр - Поновіть Моніку

11
Мені здається, що єдиною причиною, що немає <Primitive>Streamдля кожного примітивного типу, є те, що він занадто сильно роздує API. Правильне запитання, яке потрібно задати - "чому взагалі існує IntStream?" і прикрою відповіддю є те, що система типу Java недостатньо розроблена, щоб виражати Stream<int>без усіх витрат на використання продуктивності Integer. Якби у Java були типи значень, які можна було б виділити в стек або вставити безпосередньо в рядок в інші структури даних, не було б такої потреби в іншомуStream<T>
Олександр - Відновити Моніку

32

Звичайно, відповідь « адже саме так вирішили дизайнери ». Немає технічної причини, чому CharStreamне могло б існувати.

Якщо ви хочете виправдання, вам зазвичай потрібно повернути список розсилки OpenJDK *. Документація JDK не має звичаю пояснювати, чому все так і є.

Хтось запитав

Використовувати IntStream для представлення потоку char / byte трохи незручно. Чи слід також додати CharStream та ByteStream?

Відповідь Брайана Геца (Java Language Architect) говорить

Коротка відповідь: ні.

Не варто більше 100K + слід JDK для цих форм, які використовуються майже ніколи. І якби ми додали ці, хтось вимагав би коротких, плаваючих або булевих.

По-іншому, якби люди наполягали на тому, що ми маємо всі примітивні спеціалізації, у нас не було б примітивних спеціалізацій. Що було б гірше, ніж статус-кво.

Джерело

Те ж він говорить і в інших місцях

Якщо ви хочете розібратися з ними як символи, ви можете їх легко замінити на символи досить легко. Не здається достатньо важливим випадком використання, щоб мати цілий набір потоків. (Те саме з Короткий, Байт, Поплавок).

Джерело

TL; DR: Не варто витрат на обслуговування.


* Якщо вам цікаво, я використовував запит google

site:http://mail.openjdk.java.net/ charstream

2
Чи може хтось уточнити, що вони мають на увазі 100K+ of JDK footprint?
yassin

3
@yassin Хтось повинен написати код. Він підрахував, що кожна спеціалізація потоку становить понад 100 000 рядків коду
Майкл

3
@BulgarSadykov Такі запитання про " чому X схожий на Y " часто закриваються на основі думки, оскільки неможливо прочитати розум оригінального автора, і, якщо вони не виявляться, все, що ви отримаєте, - це здогади. Якщо я запитаю "як мені надіслати POST-запит з HTTP-клієнтом Apache?", Кожен, хто знайомий з бібліотекою, може відповісти на це. Чому бібліотека створена так, як це зазвичай, відповісти неможливо. Єдина причина, що ми можемо відповісти на це насправді, це те, що є загальнодоступний запис їхніх розмов. Саме це я намагався досягти з першого речення.
Майкл

2
@BulgarSadykov також нагадує про це, згадує блог Еріка Ліпперта, про C #, але на тему "чому функція Foo не реалізована мовою" stackoverflow.com/a/5588850/479251
Pac0,

2
@BulgarSadykov З повагою не згоден. Знову повторюю свій приклад запитання про те, " як я надсилаю POST-запит з HTTP-клієнтом Apache? ". Відповідь на це питання явно не починається з " тому, що це вирішили дизайнери ". Я не змінюю формулювання, вибачте.
Майкл

7

Це не лише charмасиви, які не підтримуються.

Існує лише 3 типи примітивних потоків - IntStream, LongStreamі DoubleStream.

В результаті Arraysє методи, які перетворюють int[], long[]і double[]у відповідні примітивні потоки.

Там немає відповідних методів boolean[], byte[], short[], char[]і float[], так як ці примітивні типів мають відповідні примітивні потоки.


4
"Оскільки ці примітивні типи не мають відповідних примітивних потоків." Тоді наступним питанням було б "чому"?
Федеріко Клез Куллока

7
@FedericoklezCulloca, на яке подано відповідне запитання тут,
Еран

6

charє залежною частиною String- зберігання значень UTF-16. Символ Unicode, кодова точка , іноді є сурогатною парою знаків. Отже, будь-яке просте рішення з символами охоплює лише частину домену Unicode.

Був час, який charмав своє право бути публічним типом. Але в наш час, краще використовувати кодові точки , IntStream. Потік чарівності не міг прямо впоратися із сурогатними парами.

Інша більш прозаїчна причина полягає в тому, що модель "процесора" JVM використовує intяк найменший "регістр", зберігаючи булеві, байтові, шорти, а також символи в такому розмірі місця для зберігання. Щоб не обов'язково роздувати класи java, один утримався від усіх можливих варіантів копіювання.

В майбутньому можна очікувати, що примітивні типи, які можуть функціонувати як параметри загального типу, забезпечують a List<int>. Тоді ми можемо побачити Stream<char>.

На даний момент краще уникати char, а можливо, використовувати java.text.Normalizerдля унікальної канонічної форми точок коду / рядків Unicode.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.