While going through the ways of converting primitive arrays to Streams, I found that char[]
are not supported while other primitive array types are supported. Any particular reason to leave them out in the stream?

- 202,337
- 40
- 393
- 406

- 2,046
- 3
- 23
- 46
-
3https://stackoverflow.com/questions/22435833/why-is-string-chars-a-stream-of-ints-in-java-8 This thread IMO addresses a related question – Mark Bramnik Feb 03 '20 at 10:42
4 Answers
Of course, the answer is "because that's what the designers decided". There is no technical reason why CharStream
could not exist.
If you want justification, you usually need to turn the the OpenJDK mailing list*. The JDK's documentation is not in the habit of justifying why anything is why it is.
Someone asked
Using IntStream to represent char/byte stream is a little inconvenient. Should we add CharStream and ByteStream as well?
The reply from Brian Goetz (Java Language Architect) says
Short answer: no.
It is not worth another 100K+ of JDK footprint each for these forms which are used almost never. And if we added those, someone would demand short, float, or boolean.
Put another way, if people insisted we had all the primitive specializations, we would have no primitive specializations. Which would be worse than the status quo.
He also says the same elsewhere
If you want to deal with them as chars, you can downcast them to chars easily enough. Doesn't seem like an important enough use case to have a whole 'nother set of streams. (Same with Short, Byte, Float).
TL;DR: Not worth the maintenance cost.
*In case you're curious, the google query I used was
site:http://mail.openjdk.java.net/ charstream

- 41,989
- 11
- 82
- 128
-
2
-
3@yassin Someone has to write the code. He is estimating that each specialization of stream is more than 100,000 lines of code – Michael Feb 04 '20 at 08:41
-
You are basically saying there is no justification and then providing reasonable (at least to me) justification :-) – bsk Feb 04 '20 at 12:16
-
Starting your answer with "because that's what the designers decided" is not constructive. All decisions are made by designers, no need to state it. There was a reason behind that decision and you should start with it instead of stating obvious. – bsk Feb 04 '20 at 13:06
-
3@BulgarSadykov Such questions about "*why X is like Y*" are often closed as opinion-based because it is impossible to read the mind of the original author and, unless they happen to show up, all you will get is conjecture. If I ask "how do I send a POST request with Apache's HTTP client?", anyone familiar with the library can answer that. *Why* a library is designed the way it is is usually impossible to answer. The only reason we are able to answer this *really* is because there's a public record of their conversations. That's what I was trying to get at with the first sentence. – Michael Feb 04 '20 at 13:31
-
2@BulgarSadykov it also reminds of this, mentions Eric Lippert's blog, about C#, but on the topic of "why Foo feature is not implemented in the language" https://stackoverflow.com/a/5588850/479251 – Pac0 Feb 04 '20 at 16:04
-
I'm just saying that starting your answer with "because that's what the designers decided" is useless and unhelpful, otherwise virtually every answer on stackoverflow should start with that phrase. – bsk Feb 06 '20 at 10:49
-
2@BulgarSadykov Respectfully disagree. Again, I repeat my example question of "*how do I send a POST request with Apache's HTTP client?*". An answer to that question clearly doesn't start with "*because that's what the designers decided*". I'm not changing the wording, sorry. – Michael Feb 06 '20 at 11:02
As Eran said, it's not the only one missing.
A BooleanStream
would be useless, a ByteStream
(if it existed) can be handled as an InputStream
or converted to IntStream
(as can short
), and float
can be handled as a DoubleStream
.
As char
is not able to represent all characters anyway (see linked), it would be a bit of a legacy stream. Although most people don't have to deal with codepoints anyway, so it can seem strange. I mean you use String.charAt()
without thinking "this doesn't actually work in all cases".
So some things were left out because they weren't deemed that important. As said by JB Nizet in the linked question:
The designers explicitly chose to avoid the explosion of classes and methods by limiting the primitive streams to 3 types, since the other types (char, short, float) can be represented by their larger equivalent (int, double) without any significant performance penalty.
The reason BooleanStream
would be useless, is because you only have 2 values and that limits the operations a lot. There's no mathematical operations to do, and how often are you working with lots of boolean values anyway?
As can be seen from the comments, a BooleanStream
is not needed. If it were, there would be a lot of actual use cases instead of theoretical situations, a use case going back to Java 1.4, and a fallacious comparison to while
loop.

- 72,141
- 5
- 83
- 121
-
7
-
13Is it really unreasonable to assume someone could need to do, e.g. `reduce(Boolean::logicalAnd)` or `reduce(Boolean::logicalOr)`, on a `boolean[]`? After all, the methods `logicalAnd` and `logicalOr` have been added in Java 8, so I can do these reduction operations of a `Stream
`… By the way, you can stream over a `char[]` as easy as `CharBuffer.wrap(array).chars()` or `CharBuffer.wrap(array).codePoints()` , depending which semantic you prefer. – Holger Feb 03 '20 at 11:38 -
2@Holger just because `Boolean::logicalAnd` exists, it doesn't necessarily warrant the existence of a `BooleanStream`. Those can be used in non-stream lambda situations after all. I can imagine that someone would **want** to do `reduce(Boolean::logicalAnd)`, but in no case does anyone **need** to do it. – Kayaman Feb 03 '20 at 11:48
-
4I don't see what argument you're trying to make. In its extreme form: "I can imagine that someone would would want to do `while (i < limit)`, but in no case does anyone *need* to do it [over using branch and jump assembly instructions]" – Alexander Feb 03 '20 at 19:18
-
11It seems to me like the only reason there's no `
Stream` for every primitive type is because it'll bloat the API too much. The correct question to be asking is "why is there `IntStream`, at all?" and the unfortunate answer is because Java's type system isn't fleshed out enough to express `Stream – Alexander Feb 03 '20 at 19:20` without all of the performance expense of using `Integer`. If Java had value types, which could be allocated on the stack or embed directly in-line within other data structures, there would be no such need for anything besides `Stream ` -
2It should be noted that the overhead of boxing a boolean is much lower than boxing any other primitive type because there can only be 2 instances, therefore no memory allocation is required. – PhilipRoman Feb 03 '20 at 19:56
-
@Alexander-ReinstateMonica and bloat is the only reason, and that has been stated. I just emphasised the uselessness of a `BooleanStream` in response to glglgl. You're free to tell me of a situation when you were working with a large amount of `booleans` and wished you could stream them and I'll reconsider my answer. Joop Eggen addressed the issue of primitive generic types in his answer, but we're going to have to play with the cards we were dealt. – Kayaman Feb 04 '20 at 06:45
-
@Kayaman Whenever you have an array of a "wrong" (i. e. unsupported) type (for whatever reason), you have to first rebuild it in a boxed way, before you can turn it into a stream. That's a bit annoying. – glglgl Feb 04 '20 at 09:19
-
"You're free to tell me of a situation when you were working with a large amount of booleans and wished you could stream them and I'll reconsider my answer." Polling a hardware button, and converting raw samples (on/off) into events (low, rising edge, high, falling edge). – Alexander Feb 04 '20 at 14:14
-
@Alexander-ReinstateMonica so how did you end up doing it, and was the solution dramatically poorer than it would've been with a `BooleanStream`? – Kayaman Feb 05 '20 at 08:18
-
@Kayaman This was on an old JVM (1.4! D:) I had a pretty complex imperative solution, that could have been replaced with the Java stream equivalent of this psudocode: `zip(buttonStream, buttonStream.dorpFirst()).map(labelEvent)`., where `labelEvent` is a method that take a pair of doubles and labels them as `low`, `risingEdge`, `high`, `fallingEdge`. You could then add in throttling operators, to handle switch debouncing (which was very hard to do, in imperative code.) – Alexander Feb 05 '20 at 14:48
It's not only char
arrays that are not supported.
There are only 3 types of primitive streams - IntStream
, LongStream
and DoubleStream
.
As a result, Arrays
has methods that convert int[]
, long[]
and double[]
to the corresponding primitive streams.
There are no corresponding methods for boolean[]
, byte[]
, short[]
, char[]
and float[]
, since these primitive types have no corresponding primitive streams.

- 387,369
- 54
- 702
- 768
-
4*"Since these primitive types have no corresponding primitive streams."* Then the followup question would be "why"? – Federico klez Culloca Feb 03 '20 at 10:38
-
7@FedericoklezCulloca that followup question is answered [here](https://stackoverflow.com/questions/22435833/why-is-string-chars-a-stream-of-ints-in-java-8/22497858#22497858) – Eran Feb 03 '20 at 10:42
char
is a dependent part of String
- storing UTF-16 values. A Unicode symbol, a code point, is sometimes a surrogate pair of chars. So any simple solution with chars only covers part of the Unicode domain.
There was a time that char
had its own right to be a public type. But nowadays it is better to use code points, an IntStream
. A stream of char could not straightforwardly handle surrogate pairs.
The other more prosaic reason is that the JVM "processor" model uses an int
as smallest "register", keeping booleans, bytes, shorts and also chars in such an int sized storage location. To not necessarily bloat java classes, one refrained from all possible copy variants.
In the far future one might expect primitive types allowed to function as generic type parameters, providing a List<int>
. Then we might see a Stream<char>
.
For the moment better avoid char
, and maybe use java.text.Normalizer
for a unique canonical form of code points / Unicode strings.

- 41,989
- 11
- 82
- 128

- 107,315
- 7
- 83
- 138