Por que char [] as únicas matrizes não são suportadas por Arrays.stream ()?

43

Ao analisar as maneiras de converter matrizes primitivas em Streams, descobri que char[]elas não são suportadas enquanto outros tipos de matrizes primitivas são suportadas. Algum motivo específico para deixá-los de fora no fluxo?

motoqueiro Fantasma
fonte
3
stackoverflow.com/questions/22435833/… Este tópico IMO aborda uma questão relacionada
Mark Bramnik 03/02

Respostas:

31

Como Eran disse, não é o único que falta.

A BooleanStreamseria inútil, a ByteStream(se existir) pode ser tratado como um InputStreamou convertido em IntStream(como pode short) e floatpode ser tratado como um DoubleStream.

Como charnão é capaz de representar todos os caracteres de qualquer maneira (veja o link), seria um pouco um fluxo herdado. Embora a maioria das pessoas não precise lidar com pontos de código de qualquer maneira, isso pode parecer estranho. Quero dizer, você usa String.charAt()sem pensar "isso realmente não funciona em todos os casos".

Então, algumas coisas foram deixadas de fora porque não foram consideradas tão importantes. Como disse JB Nizet na pergunta vinculada :

Os designers escolheram explicitamente evitar a explosão de classes e métodos limitando os fluxos primitivos a 3 tipos, já que os outros tipos (char, short, float) podem ser representados por seu equivalente maior (int, double) sem nenhuma penalidade significativa no desempenho.

O motivo BooleanStreamseria inútil, porque você tem apenas 2 valores e isso limita muito as operações. Não há operações matemáticas a serem feitas, e com que frequência você trabalha com muitos valores booleanos?

Kayaman
fonte
7
"A BooleanStreamseria inútil": por quê?
glglgl
12
É realmente irracional supor que alguém possa precisar fazer, por exemplo , reduce(Boolean::logicalAnd)ou reduce(Boolean::logicalOr)em um boolean[]? Afinal, os métodos logicalAnde logicalOrforam adicionados no Java 8, para que eu possa fazer essas operações de redução de um Stream<Boolean>… Aliás, você pode transmitir por um char[]tão fácil quanto CharBuffer.wrap(array).chars()ou CharBuffer.wrap(array).codePoints(), dependendo da semântica que preferir.
Holger
2
@ Holger apenas porque Boolean::logicalAndexiste, não necessariamente garante a existência de um BooleanStream. Afinal, eles podem ser usados ​​em situações lambda sem fluxo. Eu posso imaginar que alguém iria querer fazer reduce(Boolean::logicalAnd), mas em nenhum caso qualquer necessidade de fazê-lo.
Kayaman 03/02
4
Não vejo que argumento você está tentando fazer. Em sua forma extrema: "Eu posso imaginar que alguém gostaria de fazer while (i < limit), mas em nenhum caso alguém precisa fazê-lo [usando instruções de montagem de ramificação e salto]"
Alexander - Reinstate Monica
11
Parece-me que a única razão pela qual não existe nenhum <Primitive>Streamtipo primitivo é porque ela inchará muito a API. A pergunta correta a ser feita é "por que existe IntStream?" e a resposta infeliz é que o sistema de tipos do Java não é desenvolvido o suficiente para ser expresso Stream<int>sem toda a despesa de desempenho do uso Integer. Se o Java tivesse tipos de valor, que poderiam ser alocados na pilha ou incorporados diretamente em linha em outras estruturas de dados, não haveria essa necessidade de mais nadaStream<T>
Alexander - Reinstate Monica
32

Obviamente, a resposta é " porque é isso que os designers decidiram ". Não há razão técnica para CharStreamnão existir.

Se você deseja justificativa, geralmente precisa virar a lista de discussão do OpenJDK *. A documentação do JDK não tem o hábito de justificar por que razão existe alguma coisa.

Alguém perguntou

Usar o IntStream para representar o fluxo de caracteres / bytes é um pouco inconveniente. Devemos adicionar também CharStream e ByteStream?

A resposta de Brian Goetz (Java Language Architect) diz

Resposta curta: não.

Não vale mais 100K + da pegada JDK cada um para esses formulários que são usados ​​quase nunca. E se os adicionássemos, alguém exigiria short, float ou boolean.

Dito de outra forma, se as pessoas insistissem que tínhamos todas as especializações primitivas, não teríamos especializações primitivas. O que seria pior que o status quo.

Fonte

Ele também diz o mesmo em outro lugar

Se você deseja lidar com eles como caracteres, você pode baixá-los para caracteres com bastante facilidade. Não parece ser um caso de uso suficientemente importante para ter um conjunto completo de fluxos. (Mesmo com curto, byte, flutuador).

Fonte

TL; DR: Não vale o custo de manutenção.


* Caso você esteja curioso, a consulta do Google que usei foi

site:http://mail.openjdk.java.net/ charstream
Michael
fonte
2
Alguém poderia esclarecer o que eles querem dizer com isso 100K+ of JDK footprint?
yassin
3
@yassin Alguém tem que escrever o código. Ele está estimando que cada especialização de fluxo tem mais de 100.000 linhas de código
Michael
3
@BulgarSadykov Tais perguntas sobre " por que X é como Y " são freqüentemente fechadas como baseadas em opiniões, porque é impossível ler a mente do autor original e, a menos que elas apareçam, tudo o que você terá é conjectura. Se eu perguntar "como envio uma solicitação POST com o cliente HTTP do Apache?", Qualquer pessoa familiarizada com a biblioteca pode responder a isso. Por que uma biblioteca é projetada da maneira que é geralmente é impossível responder. A única razão pela qual somos capazes de responder a isso realmente é porque há um registro público de suas conversas. Era o que eu estava tentando entender com a primeira frase.
Michael
2
@BulgarSadykov também lembra disso, menciona o blog de Eric Lippert, sobre C #, mas sobre o tópico "por que o recurso Foo não está implementado no idioma" stackoverflow.com/a/5588850/479251
Pac0
2
@BulgarSadykov Discordo respeitosamente. Novamente, repito minha pergunta de exemplo de " como envio uma solicitação POST com o cliente HTTP do Apache? ". Uma resposta a essa pergunta claramente não começa com " porque foi o que os designers decidiram ". Não estou mudando a redação, desculpe.
Michael
7

Não são apenas as charmatrizes que não são suportadas.

Existem apenas 3 tipos de fluxos primitivos - IntStream, LongStreame DoubleStream.

Como resultado, Arraystem métodos que convertem int[], long[]e double[]para os fluxos de primitivas correspondentes.

Não há métodos correspondentes para boolean[], byte[], short[], char[]e float[], uma vez que estes tipos primitivos não têm fluxos primitivos correspondente.

Eran
fonte
4
"Como esses tipos primitivos não têm fluxos primitivos correspondentes". Então a pergunta seguinte seria "por que"?
Federico klez Culloca 03/02
7
@FedericoklezCulloca essa pergunta de acompanhamento é respondida aqui
Eran
6

charé uma parte dependente do Stringarmazenamento de valores UTF-16. Às vezes , um símbolo Unicode, um ponto de código , é um par substituto de caracteres. Portanto, qualquer solução simples com caracteres cobre apenas parte do domínio Unicode.

Houve um tempo que chartinha seu próprio direito de ser do tipo público. Mas hoje em dia é melhor usar pontos de código , um IntStream. Um fluxo de caracteres não podia lidar diretamente com pares substitutos.

A outra razão mais prosaica é que o modelo de "processador" da JVM usa o intmenor "registro", mantendo booleanos, bytes, shorts e também caracteres em um local de armazenamento de tamanho int. Para não necessariamente inchar as classes java, uma se absteve de todas as variantes de cópia possíveis.

Em um futuro distante, pode-se esperar que tipos primitivos possam funcionar como parâmetros de tipo genérico, fornecendo a List<int>. Então podemos ver a Stream<char>.

Por enquanto, é melhor evitar chare talvez usar java.text.Normalizerpara uma forma canônica exclusiva de pontos de código / seqüências de caracteres Unicode.

Joop Eggen
fonte