Podczas omawiania sposobów konwertowania prymitywnych tablic na strumienie okazało się, że char[]
nie są one obsługiwane, podczas gdy obsługiwane są inne pierwotne typy tablic. Czy jest jakiś konkretny powód, aby pominąć je w strumieniu?
Podczas omawiania sposobów konwertowania prymitywnych tablic na strumienie okazało się, że char[]
nie są one obsługiwane, podczas gdy obsługiwane są inne pierwotne typy tablic. Czy jest jakiś konkretny powód, aby pominąć je w strumieniu?
Odpowiedzi:
Jak powiedział Eran, nie tylko on zaginął.
A BooleanStream
byłby bezużyteczny, a ByteStream
(jeśli istniałby ) może być traktowany jako InputStream
lub konwertowany na IntStream
(jak może short
) i float
może być obsługiwany jako DoubleStream
.
Ponieważ i char
tak nie jest w stanie reprezentować wszystkich znaków (patrz link), byłby to nieco starszy strumień. Chociaż większość ludzi i tak nie musi mieć do czynienia ze współrzędnymi kodowymi, więc może się to wydawać dziwne. Mam na myśli, że używasz String.charAt()
bez myślenia „to nie działa we wszystkich przypadkach”.
Dlatego niektóre rzeczy zostały pominięte, ponieważ nie uznano ich za tak ważne. Jak powiedział JB Nizet w powiązanym pytaniu :
Projektanci wyraźnie postanowili uniknąć eksplozji klas i metod, ograniczając prymitywne strumienie do 3 typów, ponieważ inne typy (char, short, float) mogą być reprezentowane przez ich większy odpowiednik (int, double) bez żadnej znaczącej utraty wydajności.
Powód BooleanStream
byłby bezużyteczny, ponieważ masz tylko 2 wartości, co znacznie ogranicza operacje. Nie trzeba wykonywać żadnych operacji matematycznych, a jak często pracujesz z wieloma wartościami logicznymi?
BooleanStream
byłoby bezużyteczne”: dlaczego?
reduce(Boolean::logicalAnd)
Lub reduce(Boolean::logicalOr)
na boolean[]
? W końcu metody logicalAnd
i logicalOr
zostały dodane w Javie 8, więc mogę wykonać te operacje redukcji Stream<Boolean>
… Nawiasem mówiąc, możesz przesyłać strumieniowo char[]
tak łatwo CharBuffer.wrap(array).chars()
lub CharBuffer.wrap(array).codePoints()
, w zależności od tego, który semantyczny preferujesz.
Boolean::logicalAnd
, że istnieje, niekoniecznie gwarantuje istnienie BooleanStream
. Można ich jednak użyć w sytuacjach, w których lambda nie jest strumieniowe. Mogę sobie wyobrazić, że ktoś chce zrobić reduce(Boolean::logicalAnd)
, ale w żadnym wypadku nie będzie nikomu potrzebę , aby to zrobić.
while (i < limit)
, ale w żadnym wypadku nikt nie musi tego robić [za pomocą instrukcji montażu oddziału i skoku]”
<Primitive>Stream
dla którego nie ma każdego prymitywnego typu, jest to, że nadmiernie nadyma API. Prawidłowe pytanie, które należy zadać, brzmi „dlaczego IntStream
w ogóle jest?” a niefortunną odpowiedzią jest to, że system typów Java nie jest wystarczająco rozbudowany, aby wyrazić Stream<int>
bez całego wydatku związanego z wydajnością Integer
. Gdyby Java miała typy wartości, które mogłyby być przypisane do stosu lub osadzone bezpośrednio w innych strukturach danych, nie byłoby takiej potrzeby poza niczym innymStream<T>
Oczywiście odpowiedź brzmi „ bo tak postanowili projektanci ”. Nie ma technicznego powodu, dla CharStream
którego nie mógłby istnieć.
Jeśli potrzebujesz uzasadnienia, zwykle musisz zmienić listę mailingową OpenJDK *. Dokumentacja JDK nie ma zwyczaju uzasadniać, dlaczego coś jest, dlaczego tak jest.
Ktoś zapytał
Używanie IntStream do reprezentowania strumienia char / bajtów jest nieco niewygodne. Czy powinniśmy również dodać CharStream i ByteStream?
Odpowiedź Briana Goetza (architekta języka Java) mówi
Krótka odpowiedź: nie.
Każda z tych formularzy, które prawie nigdy nie są używane, nie jest warta więcej niż 100 000 JDK. Gdybyśmy to dodali, ktoś zażądałby krótkiego, zmiennoprzecinkowego lub logicznego.
Innymi słowy, gdyby ludzie upierali się, że mamy wszystkie prymitywne specjalizacje, nie mielibyśmy prymitywnych specjalizacji. Co byłoby gorsze niż status quo.
On również mówi to samo w innym miejscu
Jeśli chcesz traktować je jako znaki, możesz z łatwością zrzucić je na znaki. Nie wydaje się wystarczająco ważnym przypadkiem użycia, aby mieć cały „inny zestaw strumieni”. (To samo z Short, Byte, Float).
TL; DR: Nie warte kosztów utrzymania.
* Jeśli jesteś ciekawy, użyłem zapytania Google
site:http://mail.openjdk.java.net/ charstream
100K+ of JDK footprint
?
To nie tylko char
tablice nie są obsługiwane.
Są tylko 3 rodzaje strumieni - prymitywnych IntStream
, LongStream
i DoubleStream
.
W efekcie, Arrays
ma metody konwersji int[]
, long[]
i double[]
do odpowiednich pierwotnych strumieni.
Brak odpowiednich metod boolean[]
, byte[]
, short[]
, char[]
i float[]
, ponieważ te typy pierwotne nie ma odpowiedniego pierwotne strumienie.
char
jest zależną częścią String
- przechowywania wartości UTF-16. Symbol Unicode, punkt kodowy , jest czasem zastępczą parą znaków. Tak więc każde proste rozwiązanie z znakami obejmuje tylko część domeny Unicode.
Był czas, który char
miał własne prawo do bycia typem publicznym. Ale w dzisiejszych czasach lepiej jest użyć punktów kodowych , IntStream
. Strumień zwęglenia nie był w stanie bezpośrednio poradzić sobie z parami zastępczymi.
Innym bardziej prozaicznym powodem jest to, że model „procesora” JVM używa int
najmniejszego „rejestru”, utrzymując wartości logiczne, bajty, skróty, a także znaki w takiej wielkości pamięci. Aby niekoniecznie nadmuchać klasy Java, jedna powstrzymała się od wszystkich możliwych wariantów kopiowania.
W dalekiej przyszłości można oczekiwać, że prymitywne typy będą mogły działać jako ogólne parametry parametrów, pod warunkiem, że List<int>
. Wtedy możemy zobaczyć Stream<char>
.
Na razie lepiej unikać char
, a może używać java.text.Normalizer
unikalnej kanonicznej formy punktów kodowych / ciągów znaków Unicode.