Warum sind char [] die einzigen Arrays, die von Arrays.stream () nicht unterstützt werden?

43

Beim Durchlaufen der Konvertierung primitiver Arrays in Streams stellte ich fest, dass diese char[]nicht unterstützt werden, während andere primitive Array-Typen unterstützt werden. Gibt es einen besonderen Grund, sie im Stream auszulassen?

Geisterfahrer
quelle
3
stackoverflow.com/questions/22435833/… Dieser Thread IMO adressiert eine verwandte Frage
Mark Bramnik

Antworten:

31

Wie Eran sagte, ist es nicht der einzige, der fehlt.

A BooleanStreamwäre nutzlos, a ByteStream(falls vorhanden) kann als behandelt InputStreamoder in IntStream(wie möglich short) konvertiert und floatals DoubleStream.

Da charohnehin nicht alle Zeichen dargestellt werden können (siehe verlinkt), wäre es ein bisschen wie ein Legacy-Stream. Obwohl die meisten Leute sowieso nicht mit Codepunkten umgehen müssen, kann es seltsam erscheinen. Ich meine, Sie verwenden, String.charAt()ohne zu denken, "das funktioniert nicht in allen Fällen".

Einige Dinge wurden ausgelassen, weil sie nicht so wichtig waren. Wie von JB Nizet in der verknüpften Frage gesagt :

Die Designer haben sich ausdrücklich dafür entschieden, die Explosion von Klassen und Methoden zu vermeiden, indem sie die primitiven Streams auf drei Typen beschränkten, da die anderen Typen (char, short, float) durch ihr größeres Äquivalent (int, double) ohne signifikante Leistungseinbußen dargestellt werden können.

Der Grund BooleanStreamwäre nutzlos, weil Sie nur 2 Werte haben und dies die Operationen stark einschränkt. Es gibt keine mathematischen Operationen und wie oft arbeiten Sie überhaupt mit vielen booleschen Werten?

Kayaman
quelle
7
"A BooleanStreamwäre nutzlos": warum?
glglgl
12
Ist es wirklich unvernünftig anzunehmen, dass jemand etwas tun muss, z. B. reduce(Boolean::logicalAnd)oder reduce(Boolean::logicalOr)auf einem boolean[]? Immerhin wurden die Methoden logicalAndund logicalOrin Java 8 hinzugefügt, damit ich diese Reduktionsoperationen von a ausführen kann. Stream<Boolean>Übrigens können Sie über eine char[]so einfache wie CharBuffer.wrap(array).chars()oder streamen CharBuffer.wrap(array).codePoints(), je nachdem, welche Semantik Sie bevorzugen.
Holger
2
@Holger nur weil es Boolean::logicalAndexistiert, garantiert es nicht unbedingt die Existenz eines BooleanStream. Diese können schließlich in Lambda-Situationen ohne Strom verwendet werden. Ich kann mir vorstellen , dass jemand möchte zu tun reduce(Boolean::logicalAnd), aber in keinem Fall hat jemand Notwendigkeit , es zu tun.
Kayaman
4
Ich verstehe nicht, welches Argument Sie vorbringen wollen. In seiner extremen Form: „Ich , dass jemand sich vorstellen kann , würde würde tun wollen while (i < limit), aber in keinem Fall hat jemand Notwendigkeit , es zu tun [über Zweig mit und Montageanleitung springen]“
Alexander - wieder einzusetzen Monica
11
Mir scheint, der einzige Grund, warum es <Primitive>Streamfür jeden primitiven Typ kein Nein gibt, ist, dass die API dadurch zu stark aufgebläht wird. Die richtige Frage lautet: "Warum gibt es IntStreamüberhaupt?" und die unglückliche Antwort ist, dass das Typensystem von Java nicht ausreichend ausgearbeitet ist, um es Stream<int>ohne den gesamten Leistungsaufwand der Verwendung auszudrücken Integer. Wenn Java Werttypen hätte, die auf dem Stapel zugewiesen oder direkt in andere Datenstrukturen eingebettet werden könnten, wäre nichts anderes erforderlichStream<T>
Alexander - Reinstate Monica
32

Die Antwort lautet natürlich " weil die Designer das entschieden haben ". Es gibt keinen technischen Grund, warum CharStreames nicht existieren könnte.

Wenn Sie eine Begründung wünschen, müssen Sie normalerweise die OpenJDK-Mailingliste * aktivieren. Die Dokumentation des JDK hat nicht die Gewohnheit zu rechtfertigen, warum irgendetwas der Grund ist, warum es ist.

Jemand fragte

Die Verwendung von IntStream zur Darstellung des Zeichen- / Byte-Streams ist etwas unpraktisch. Sollten wir auch CharStream und ByteStream hinzufügen?

Die Antwort von Brian Goetz (Java Language Architect) lautet

Kurze Antwort: nein.

Für diese Formulare, die fast nie verwendet werden, ist es nicht wert, jeweils mehr als 100.000 JDK-Footprint zu verwenden. Und wenn wir diese hinzufügen würden, würde jemand Short, Float oder Boolean verlangen.

Anders ausgedrückt, wenn die Leute darauf bestehen würden, dass wir alle primitiven Spezialisierungen haben, hätten wir keine primitiven Spezialisierungen. Welches wäre schlimmer als der Status Quo.

Quelle

Das sagt er auch anderswo

Wenn Sie sie als Zeichen behandeln möchten, können Sie sie leicht genug auf Zeichen herabstufen. Scheint nicht wichtig genug zu sein, um eine ganze Reihe weiterer Streams zu haben. (Gleiches gilt für Short, Byte, Float).

Quelle

TL; DR: Die Wartungskosten sind es nicht wert.


* Falls Sie neugierig sind, war die von mir verwendete Google-Abfrage

site:http://mail.openjdk.java.net/ charstream
Michael
quelle
2
Könnte jemand klarstellen, was er damit meint 100K+ of JDK footprint?
Yassin
3
@yassin Jemand muss den Code schreiben. Er schätzt, dass jede Spezialisierung des Streams mehr als 100.000 Codezeilen umfasst
Michael
3
@BulgarSadykov Solche Fragen zu " Warum X wie Y ist " werden oft als meinungsbasiert geschlossen, da es unmöglich ist, die Gedanken des ursprünglichen Autors zu lesen, und wenn sie nicht zufällig auftauchen, erhalten Sie nur Vermutungen. Wenn ich frage "Wie sende ich eine POST-Anfrage mit dem HTTP-Client von Apache?", Kann jeder, der mit der Bibliothek vertraut ist, darauf antworten. Warum eine Bibliothek so gestaltet ist, wie sie ist, ist normalerweise nicht zu beantworten. Der einzige Grund, warum wir dies wirklich beantworten können, ist, dass es eine öffentliche Aufzeichnung ihrer Gespräche gibt. Das habe ich mit dem ersten Satz versucht.
Michael
2
@BulgarSadykov es erinnert auch daran, erwähnt Eric Lipperts Blog über C #, aber zum Thema "Warum die Foo-Funktion nicht in der Sprache implementiert ist" stackoverflow.com/a/5588850/479251
Pac0
2
@BulgarSadykov Respektlos widersprechen. Wiederhole ich meine Beispielfrage " Wie sende ich eine POST-Anfrage mit dem HTTP-Client von Apache? ". Eine Antwort auf diese Frage beginnt eindeutig nicht mit " weil die Designer dies beschlossen haben ". Ich ändere den Wortlaut nicht, sorry.
Michael
7

Es werden nicht nur charArrays nicht unterstützt.

Es gibt nur drei Arten von primitiven Strömen - IntStream, LongStreamundDoubleStream .

Als Ergebnis Arrayshat Methoden, die konvertieren int[], long[]unddouble[] in die entsprechenden primitiven Streams.

Es gibt keine entsprechenden Methoden für boolean[], byte[], short[], char[]und float[], da diese primitiven Typen haben keine primitive Strömen entsprechen.

Eran
quelle
4
"Da diese primitiven Typen keine entsprechenden primitiven Ströme haben." Dann wäre die Folgefrage "warum"?
Federico klez Culloca
7
@FedericoklezCulloca diese Folgefrage wird hier
Eran
6

charist ein abhängiger Teil von String- Speichern von UTF-16-Werten. Ein Unicode-Symbol, ein Codepunkt , ist manchmal ein Ersatzzeichenpaar. Daher deckt jede einfache Lösung mit Zeichen nur einen Teil der Unicode-Domäne ab.

Es gab eine Zeit, chardie ihr eigenes Recht hatte, ein öffentlicher Typ zu sein. Aber heutzutage ist es besser , verwenden Codepunkte ein IntStream. Ein Saiblingstrom konnte Ersatzpaare nicht einfach handhaben.

Der andere prosaischere Grund ist, dass das JVM- "Prozessor" -Modell ein intso kleinstes "Register" verwendet, dass Boolesche Werte, Bytes, Kurzschlüsse und auch Zeichen an einem Speicherort mit einer solchen Größe gespeichert werden. Um Java-Klassen nicht unbedingt aufzublähen, verzichtete man auf alle möglichen Kopiervarianten.

In ferner Zukunft könnte man erwarten, dass primitive Typen als generische Typparameter fungieren dürfen, sofern a List<int>. Dann könnten wir eine sehen Stream<char>.

Vermeiden Sie es im Moment besser charund verwenden Sie es möglicherweise java.text.Normalizerfür eine eindeutige kanonische Form von Codepunkten / Unicode-Zeichenfolgen.

Joop Eggen
quelle