¿Por qué son char [] los únicos arreglos no admitidos por Arrays.stream ()?

43

Mientras revisaba las formas de convertir matrices primitivas en Streams, descubrí que char[]no son compatibles mientras que otros tipos de matrices primitivas son compatibles. ¿Alguna razón en particular para dejarlos fuera de la corriente?

jinete Fantasma
fuente
3
stackoverflow.com/questions/22435833/… Este hilo IMO aborda una pregunta relacionada
Mark Bramnik

Respuestas:

31

Como dijo Eran, no es el único que falta.

A BooleanStreamsería inútil, a ByteStream(si existiera) puede manejarse como InputStreamo convertirse a IntStream(como puede short), y floatpuede manejarse como a DoubleStream.

Como charno es capaz de representar todos los caracteres de todos modos (ver relacionado), sería un poco de una corriente legado. Aunque la mayoría de las personas no tienen que lidiar con puntos de código de todos modos, puede parecer extraño. Me refiero a que usas String.charAt()sin pensar "esto en realidad no funciona en todos los casos".

Así que algunas cosas quedaron fuera porque no se consideraron tan importantes. Como dijo JB Nizet en la pregunta vinculada :

Los diseñadores decidieron explícitamente evitar la explosión de clases y métodos limitando las corrientes primitivas a 3 tipos, ya que los otros tipos (char, short, float) pueden representarse por su equivalente más grande (int, double) sin ninguna penalización de rendimiento significativa.

La razón BooleanStreamsería inútil, porque solo tiene 2 valores y eso limita mucho las operaciones. No hay operaciones matemáticas que hacer, y ¿con qué frecuencia está trabajando con muchos valores booleanos de todos modos?

Kayaman
fuente
77
"A BooleanStreamsería inútil": ¿por qué?
glglgl
12
¿Es realmente irrazonable suponer que alguien podría tener que hacer, por ejemplo , reduce(Boolean::logicalAnd)o reduce(Boolean::logicalOr)en un boolean[]? Después de todo, los métodos logicalAndy logicalOrse han añadido en Java 8, por lo que puedo hacer estas operaciones de reducción de un Stream<Boolean>... Por cierto, se puede transmitir a través de una char[]tan fácil como CharBuffer.wrap(array).chars()o CharBuffer.wrap(array).codePoints(), según el cual semántica lo prefiere.
Holger
2
@Holger solo porque Boolean::logicalAndexiste, no necesariamente garantiza la existencia de a BooleanStream. Esos pueden usarse en situaciones lambda que no son stream después de todo. Me imagino que alguien querría hacerlo reduce(Boolean::logicalAnd), pero en ningún caso nadie necesita hacerlo.
Kayaman
44
No veo qué argumento estás tratando de hacer. En su forma extrema: "Me imagino que alguien querría hacerlo while (i < limit), pero en ningún caso alguien tiene que hacerlo [sobre el uso de las instrucciones de montaje de rama y salto]"
Alexander - Restablece Mónica
11
Me parece que la única razón por la que no hay <Primitive>Streampara cada tipo primitivo es porque hinchará demasiado la API. La pregunta correcta que debe hacerse es "¿por qué hay algo IntStream?" y la desafortunada respuesta es porque el sistema de tipos de Java no está lo suficientemente desarrollado como para expresarse Stream<int>sin todos los gastos de rendimiento del uso Integer. Si Java tuviera tipos de valor, que podrían asignarse en la pila o incrustarse directamente en línea dentro de otras estructuras de datos, no habría tanta necesidad de nada además deStream<T>
Alexander - Restablecer Mónica
32

Por supuesto, la respuesta es " porque eso es lo que decidieron los diseñadores ". No hay una razón técnica por la que CharStreamno pueda existir.

Si desea justificación, generalmente necesita activar la lista de correo de OpenJDK *. La documentación del JDK no tiene la costumbre de justificar por qué algo es por qué es.

Alguien pregunto

Usar IntStream para representar la secuencia char / byte es un poco inconveniente. ¿Deberíamos agregar CharStream y ByteStream también?

La respuesta de Brian Goetz (Java Language Architect) dice

Respuesta corta: no.

No vale más de 100K + de huella JDK cada uno para estos formularios que casi nunca se usan. Y si agregamos esos, alguien exigiría short, float o boolean.

Dicho de otra manera, si la gente insistiera en que teníamos todas las especializaciones primitivas, no tendríamos especializaciones primitivas. Lo cual sería peor que el status quo.

Fuente

También dice lo mismo en otra parte.

Si desea tratarlos como caracteres, puede convertirlos en caracteres con la suficiente facilidad. No parece un caso de uso lo suficientemente importante como para tener un conjunto completo de transmisiones. (Lo mismo con Short, Byte, Float).

Fuente

TL; DR: No vale la pena el costo de mantenimiento.


* En caso de que tenga curiosidad, la consulta de Google que utilicé fue

site:http://mail.openjdk.java.net/ charstream
Miguel
fuente
2
¿Podría alguien aclarar a qué se refieren 100K+ of JDK footprint?
Yassin
3
@yassin Alguien tiene que escribir el código. Está estimando que cada especialización de la transmisión es más de 100,000 líneas de código
Michael
3
@BulgarSadykov Estas preguntas sobre " por qué X es como Y " a menudo se cierran como basadas en opiniones porque es imposible leer la mente del autor original y, a menos que aparezcan, todo lo que obtendrá será una conjetura. Si pregunto "¿cómo envío una solicitud POST con el cliente HTTP de Apache?", Cualquier persona familiarizada con la biblioteca puede responder eso. Por qué una biblioteca está diseñada de la manera en que es, generalmente es imposible de responder. La única razón por la que podemos responder esto realmente es porque hay un registro público de sus conversaciones. A eso estaba tratando de llegar con la primera oración.
Michael
2
@BulgarSadykov también recuerda esto, menciona el blog de Eric Lippert sobre C #, pero sobre el tema "por qué la función Foo no está implementada en el lenguaje" stackoverflow.com/a/5588850/479251
Pac0
2
@BulgarSadykov Respetuosamente en desacuerdo. Nuevamente, repito mi pregunta de ejemplo de " ¿cómo envío una solicitud POST con el cliente HTTP de Apache? ". Una respuesta a esa pregunta claramente no comienza con " porque eso es lo que decidieron los diseñadores ". No estoy cambiando la redacción, lo siento.
Michael
7

No solo las charmatrices no son compatibles.

Solo hay 3 tipos de flujos primitivos IntStream, LongStreamy DoubleStream.

Como resultado, Arraystiene métodos que convierten int[], long[]y double[]a las corrientes primitivas correspondientes.

No existen métodos correspondientes para boolean[], byte[], short[], char[]y float[], puesto que estos tipos primitivos no tienen correspondiente corrientes primitivas.

Eran
fuente
44
"Dado que estos tipos primitivos no tienen corrientes primitivas correspondientes". Entonces la pregunta de seguimiento sería "¿por qué"?
Federico klez Culloca
77
@FedericoklezCulloca esa pregunta de seguimiento se responde aquí
Eran
6

chares una parte dependiente de String- almacenar valores UTF-16. Un símbolo Unicode, un punto de código , a veces es un par de caracteres sustitutos. Por lo tanto, cualquier solución simple con caracteres solo cubre parte del dominio Unicode.

Hubo un tiempo que chartenía su propio derecho a ser de tipo público. Pero hoy en día es mejor usar puntos de código , an IntStream. Una corriente de char no podía manejar directamente pares sustitutos.

La otra razón más prosaica es que el modelo de "procesador" de JVM utiliza un int"registro" más pequeño, manteniendo booleanos, bytes, cortos y también caracteres en una ubicación de almacenamiento de tamaño tan int. Para no necesariamente hinchar las clases de Java, uno se abstuvo de todas las posibles variantes de copia.

En el futuro lejano, uno podría esperar que los tipos primitivos funcionen como parámetros de tipo genérico, proporcionando a List<int>. Entonces podríamos ver a Stream<char>.

Por el momento, es mejor evitarlo chary quizás usarlo java.text.Normalizerpara una forma canónica única de puntos de código / cadenas Unicode.

Joop Eggen
fuente