Mentre studiavo i modi per convertire array primitivi in stream, ho scoperto che char[]
non sono supportati mentre sono supportati altri tipi di array primitivi. Qualche motivo particolare per lasciarli fuori nel flusso?
Mentre studiavo i modi per convertire array primitivi in stream, ho scoperto che char[]
non sono supportati mentre sono supportati altri tipi di array primitivi. Qualche motivo particolare per lasciarli fuori nel flusso?
Risposte:
Come ha detto Eran, non è l'unico mancante.
A BooleanStream
sarebbe inutile, a ByteStream
(se esistesse) può essere gestito come InputStream
o convertito in IntStream
(come può short
) e float
può essere gestito come a DoubleStream
.
Dato che char
non è in grado di rappresentare tutti i personaggi (vedi link), sarebbe un po ' un flusso legacy. Sebbene la maggior parte delle persone non abbia comunque a che fare con i punti di codice, può sembrare strano. Voglio dire che usi String.charAt()
senza pensare "questo in realtà non funziona in tutti i casi".
Quindi alcune cose sono state escluse perché non sono state ritenute così importanti. Come detto da JB Nizet nella domanda collegata :
I progettisti hanno scelto esplicitamente di evitare l'esplosione di classi e metodi limitando i flussi primitivi a 3 tipi, poiché gli altri tipi (char, short, float) possono essere rappresentati dal loro equivalente più grande (int, double) senza alcuna penalità di prestazione significativa.
Il motivo BooleanStream
sarebbe inutile, perché hai solo 2 valori e questo limita molto le operazioni. Non ci sono operazioni matematiche da fare e quanto spesso lavori con molti valori booleani?
BooleanStream
sarebbe inutile": perché?
reduce(Boolean::logicalAnd)
o reduce(Boolean::logicalOr)
, su un boolean[]
? Dopotutto, i metodi logicalAnd
e logicalOr
sono stati aggiunti in Java 8, quindi posso fare queste operazioni di riduzione di un Stream<Boolean>
... A proposito, puoi eseguire lo streaming su un modo char[]
semplice CharBuffer.wrap(array).chars()
o CharBuffer.wrap(array).codePoints()
, a seconda di quale semantico preferisci.
Boolean::logicalAnd
esiste, non garantisce necessariamente l'esistenza di a BooleanStream
. Dopotutto, possono essere utilizzati in situazioni lambda non stream. Posso immaginare che qualcuno voglia fare reduce(Boolean::logicalAnd)
, ma in nessun caso Qualcuno necessità di farlo.
while (i < limit)
, ma in nessun caso qualcuno deve farlo [usando le istruzioni di assemblaggio di salti e salti]"
<Primitive>Stream
un tipo primitivo sia perché gonfia troppo l'API. La domanda corretta da porsi è "perché c'è IntStream
?" e la sfortunata risposta è perché il sistema di tipi di Java non è abbastanza elaborato per esprimersi Stream<int>
senza tutte le spese di prestazioni dell'uso Integer
. Se Java avesse tipi di valore, che potrebbero essere allocati nello stack o incorporati direttamente in linea all'interno di altre strutture di dati, non ci sarebbe bisogno di nulla in piùStream<T>
Certo, la risposta è " perché è quello che hanno deciso i designer ". Non esiste alcun motivo tecnico per cui CharStream
non potrebbe esistere.
Se vuoi una giustificazione, di solito devi trasformare la mailing list di OpenJDK *. La documentazione del JDK non ha l'abitudine di giustificare perché qualcosa è perché è.
Qualcuno ha chiesto
L'uso di IntStream per rappresentare il flusso char / byte è un po 'scomodo. Dovremmo aggiungere anche CharStream e ByteStream?
La risposta di Brian Goetz (Java Language Architect) dice
Risposta breve: no.
Non vale altri 100 K + di impronta JDK ciascuno per questi moduli che non vengono usati quasi mai. E se aggiungessimo quelli, qualcuno richiederebbe short, float o booleano.
Detto in altro modo, se le persone insistessero sul fatto che avevamo tutte le specializzazioni primitive, non avremmo specializzazioni primitive. Quale sarebbe peggio dello status quo.
Lo dice anche altrove
Se vuoi gestirli come caratteri, puoi trasferirli in caratteri abbastanza facilmente. Non sembra un caso d'uso abbastanza importante per avere un'intera serie di flussi. (Lo stesso con Short, Byte, Float).
TL; DR: non vale i costi di manutenzione.
* Se sei curioso, la query di Google che ho usato era
site:http://mail.openjdk.java.net/ charstream
100K+ of JDK footprint
?
Non sono solo le char
matrici che non sono supportate.
Ci sono solo 3 tipi di flussi primitivi - IntStream
, LongStream
e DoubleStream
.
Come risultato, Arrays
ha metodi che convertono int[]
, long[]
e double[]
alle corrispondenti flussi primitivi.
Non esistono metodi corrispondenti per boolean[]
, byte[]
, short[]
, char[]
e float[]
, poiché questi tipi primitivi hanno alcun corrispondente flussi primitive.
char
è una parte dipendente di String
- memorizzazione dei valori UTF-16. Un simbolo Unicode, un punto di codice , a volte è una coppia surrogata di caratteri. Quindi qualsiasi soluzione semplice con caratteri copre solo una parte del dominio Unicode.
C'è stato un tempo che char
aveva il suo diritto di essere di tipo pubblico. Ma al giorno d'oggi è meglio usare i punti di codice , un IntStream
. Un flusso di caratteri non è in grado di gestire in modo diretto coppie surrogate.
L'altro motivo più prosaico è che il modello di "processore" JVM utilizza un int
"registro" come il più piccolo, mantenendo valori booleani, byte, short e anche caratteri in una posizione di archiviazione di dimensioni tali. Per non gonfiare necessariamente le classi java, una trattenuta da tutte le possibili varianti di copia.
In un futuro molto lontano ci si potrebbe aspettare che i tipi primitivi possano funzionare come parametri di tipo generico, fornendo a List<int>
. Quindi potremmo vedere a Stream<char>
.
Per il momento meglio evitare char
, e forse usare java.text.Normalizer
per una forma canonica unica di punti di codice / stringhe Unicode.