Почему char [] единственные массивы, которые не поддерживаются Arrays.stream ()?

43

Проходя через способы преобразования примитивных массивов в потоки, я обнаружил, что char[]они не поддерживаются, в то время как поддерживаются другие типы примитивных массивов. Есть какая-то конкретная причина, чтобы оставить их в потоке?

Призрачный гонщик
источник
3
stackoverflow.com/questions/22435833/… В этой теме ИМО обращается к связанному вопросу
Марк Брамник

Ответы:

31

Как сказал Эран, это не единственный пропавший.

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

Поскольку charв любом случае невозможно представить все символы (см. Ссылку), это будет немного устаревшим потоком. Хотя большинству людей в любом случае не приходится иметь дело с кодовыми точками, это может показаться странным. Я имею в виду, что вы используете, String.charAt()не думая, что «это не работает во всех случаях».

Поэтому некоторые вещи были опущены, потому что они не считались такими важными. Как сказал Дж. Б. Низет в связанном вопросе :

Разработчики явно решили избежать взрыва классов и методов, ограничив примитивные потоки тремя типами, поскольку другие типы (char, short, float) могут быть представлены их большим эквивалентом (int, double) без какого-либо существенного снижения производительности.

Причина BooleanStreamбудет бесполезной, потому что у вас есть только 2 значения, и это сильно ограничивает операции. Там нет математических операций, и как часто вы работаете с большим количеством логических значений в любом случае?

Kayaman
источник
7
«А BooleanStreamбыло бы бесполезно»: почему?
glglgl
12
Является ли это действительно разумно предположить кто - то может понадобиться , чтобы сделать, например , reduce(Boolean::logicalAnd)или reduce(Boolean::logicalOr), на boolean[]? В конце концов, методы logicalAndи logicalOrбыли добавлены в Java 8, так что я могу выполнять эти операции сокращения a Stream<Boolean>... Кстати, вы можете выполнять потоковую передачу по char[]так легко CharBuffer.wrap(array).chars()или CharBuffer.wrap(array).codePoints(), в зависимости от того, какую семантику вы предпочитаете.
Хольгер
2
@ Хольгер только потому 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 для представления потока символов / байтов немного неудобно. Должны ли мы также добавить CharStream и ByteStream?

В ответе Брайана Гетца (Java Language Architect) говорится:

Краткий ответ: нет.

Для этих форм, которые используются почти никогда, не стоит больше 100K + JDK. И если бы мы добавили их, кто-то потребовал бы short, float или boolean.

Иными словами, если бы люди настаивали на том, что у нас были все примитивные специализации, у нас не было бы примитивных специализаций. Что было бы хуже, чем статус-кво.

Источник

Он также говорит то же самое в другом месте

Если вы хотите обращаться с ними как с символами, вы можете достаточно легко превратить их в символы. Не кажется достаточно важным вариантом использования, чтобы иметь целый «другой набор потоков». (То же самое с Short, Byte, Float).

Источник

TL; DR: не стоит затрат на обслуживание.


* Если вам интересно, я использовал запрос Google:

site:http://mail.openjdk.java.net/ charstream
Майкл
источник
2
Может ли кто-нибудь уточнить, что они имеют в виду 100K+ of JDK footprint?
Ясин
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массивы, которые не поддерживаются.

Есть только три типа примитивных потоков - IntStream, LongStreamи DoubleStream.

В результате Arraysимеют методы , которые преобразуют int[], long[]и double[]к соответствующим примитивным потокам.

Там нет соответствующих методов boolean[], byte[], short[], char[]и float[], так как эти примитивные типов имеют соответствующие примитивные потоки.

Эран
источник
4
«Поскольку эти примитивные типы не имеют соответствующих примитивных потоков». Тогда последующим вопросом будет «почему»?
Федерико Клез Каллока
7
@FedericoklezCulloca ответ на этот вопрос здесь
Eran
6

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

Было время, которое charимело собственное право быть публичным типом. Но в наше время, лучше использовать кодовые точки , IntStream. Поток полукокса не может напрямую обрабатывать суррогатные пары.

Другая более прозаическая причина заключается в том, что модель «процессора» JVM использует intнаименьший «регистр», сохраняя логические значения, байты, шорты, а также символы в таком месте хранения int. Чтобы не обязательно раздувать Java-классы, нужно воздерживаться от всех возможных вариантов копирования.

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

На данный момент лучше избегать charи, возможно, использовать java.text.Normalizerдля уникальной канонической формы кодовые точки / строки Unicode.

Joop Eggen
источник