เหตุใดอักขระ char [] ไม่สนับสนุน Arays.stream () เฉพาะอาร์เรย์เท่านั้น


43

ในขณะที่ทำตามวิธีการแปลงอาร์เรย์ดั้งเดิมเป็นสตรีมฉันพบchar[]ว่าไม่ได้รับการสนับสนุนในขณะที่สนับสนุนประเภทอาร์เรย์ดั้งเดิมอื่น ๆ มีเหตุผลใดที่ทำให้พวกเขาออกจากกระแส?


3
stackoverflow.com/questions/22435833/…กระทู้นี้ IMO ตอบคำถามที่เกี่ยวข้อง
Mark Bramnik

คำตอบ:


31

อย่างที่ Eran กล่าวมันไม่ใช่สิ่งเดียวที่ขาดหายไป

BooleanStreamจะไร้ประโยชน์เป็นByteStream(ถ้ามันมีตัวตน) สามารถจัดการได้เป็นInputStreamหรือแปลงIntStream(เป็นได้short) และสามารถจัดการได้เป็นfloatDoubleStream

เนื่องจากcharไม่สามารถแสดงอักขระทั้งหมดได้ (ดูที่เชื่อมโยง) จึงเป็นบิตของการรับชมแบบดั้งเดิม แม้ว่าคนส่วนใหญ่ไม่จำเป็นต้องจัดการกับ codepoints ต่อไปดังนั้นมันอาจดูแปลก ฉันหมายถึงคุณใช้String.charAt()โดยไม่ต้องคิดว่า "มันใช้ไม่ได้กับทุกกรณี"

ดังนั้นจึงมีบางสิ่งเหลืออยู่เพราะพวกเขาไม่ถือว่าสำคัญ ตามที่กล่าวโดย JB Nizet ในคำถามที่เชื่อมโยง :

นักออกแบบเลือกที่จะหลีกเลี่ยงการระเบิดของคลาสและวิธีการอย่างชัดเจนโดย จำกัด การสตรีมแบบดั้งเดิมเป็น 3 ประเภทเนื่องจากประเภทอื่น (char, short, float) สามารถถูกแทนด้วยขนาดที่ใหญ่กว่า (int, double) โดยไม่มีการลงโทษประสิทธิภาพที่สำคัญ

เหตุผลBooleanStreamจะไร้ประโยชน์เนื่องจากคุณมีเพียง 2 ค่าและ จำกัด การดำเนินการเป็นจำนวนมาก ไม่มีการดำเนินการทางคณิตศาสตร์ที่ต้องทำและคุณทำงานกับค่าบูลีนบ่อยแค่ไหน?


7
"A BooleanStreamจะไร้ประโยชน์": ทำไม
glglgl

12
มันไม่มีเหตุผลจริง ๆ หรือไม่ที่จะสมมติว่าใครบางคนอาจต้องทำเช่นreduce(Boolean::logicalAnd)หรือreduce(Boolean::logicalOr)บน a boolean[]? ท้ายที่สุดแล้ววิธีการlogicalAndและlogicalOrได้รับการเพิ่มใน Java 8 ดังนั้นฉันสามารถดำเนินการลดลงของStream<Boolean>... โดยวิธีการที่คุณสามารถสตรีมมากกว่าchar[]ง่ายCharBuffer.wrap(array).chars()หรือCharBuffer.wrap(array).codePoints()ขึ้นอยู่กับความหมายที่คุณต้องการ
Holger

2
@Holger เพียงเพราะมีอยู่แล้วก็ไม่จำเป็นต้องรับประกันการดำรงอยู่ของที่Boolean::logicalAnd BooleanStreamสิ่งเหล่านี้สามารถใช้ในสถานการณ์แลมบ์ดาแบบไม่สตรีมได้ ฉันสามารถจินตนาการได้ว่ามีใครบางคนต้องการที่จะทำreduce(Boolean::logicalAnd)แต่ไม่มีใครที่จะต้องทำ
Kayaman

4
ฉันไม่เห็นว่าคุณกำลังพยายามโต้แย้งอะไร ในรูปแบบสุดโต่ง: "ฉันนึกภาพได้ว่ามีคนอยากจะทำwhile (i < limit)แต่ไม่ว่าในกรณีใด ๆ ก็ไม่มีใครจำเป็นต้องทำ [ใช้คำสั่งการชุมนุมสาขาและกระโดดข้าม]"
Alexander - Reinstate Monica

11
ดูเหมือนว่าฉันชอบเหตุผลเดียวที่ไม่มี<Primitive>Streamสำหรับทุกประเภทดั้งเดิมคือเพราะมันจะขยาย API มากเกินไป คำถามที่ถูกต้องที่จะถามคือ "ทำไมถึงมีIntStreamทั้งหมด?" และคำตอบที่โชคร้ายก็คือเนื่องจากระบบประเภทของ Java นั้นไม่ได้มีความสมบูรณ์เพียงพอที่จะแสดงออกStream<int>โดยไม่ต้องเสียค่าใช้จ่ายด้านประสิทธิภาพในการใช้งานIntegerทั้งหมด หาก Java มีชนิดของค่าซึ่งสามารถจัดสรรให้กับสแต็กหรือฝังแบบอินไลน์โดยตรงภายในโครงสร้างข้อมูลอื่น ๆ ก็ไม่จำเป็นต้องมีสิ่งใดนอกจากStream<T>
Alexander - Reinstate Monica

32

แน่นอนคำตอบคือ " เพราะนั่นคือสิ่งที่นักออกแบบตัดสินใจ " ไม่มีเหตุผลทางเทคนิคว่าทำไมCharStreamไม่มีตัวตน

หากคุณต้องการเหตุผลคุณจะต้องเปลี่ยนรายชื่อผู้รับจดหมาย OpenJDK * เอกสารของ JDK ไม่ได้อยู่ในลักษณะที่ว่าเหตุผลว่าทำไมอะไรถึงเป็นเหตุผล

มีคนถาม

การใช้ IntStream เพื่อแทน char / byte stream นั้นไม่สะดวกนัก เราควรเพิ่ม CharStream และ ByteStream ด้วยหรือไม่

คำตอบจาก Brian Goetz (สถาปนิกภาษา Java) กล่าวว่า

คำตอบสั้น ๆ : ไม่

มันไม่คุ้มค่าอีก 100K + ของรอยเท้า JDK สำหรับแบบฟอร์มเหล่านี้ซึ่งแทบไม่เคยใช้เลย และถ้าเราเพิ่มสิ่งเหล่านี้บางคนก็ต้องการความสั้นลอยหรือบูลีน

อีกวิธีหนึ่งถ้าคนยืนยันว่าเรามีความเชี่ยวชาญดั้งเดิมทั้งหมดเราจะไม่มีความเชี่ยวชาญดั้งเดิม ซึ่งจะแย่กว่าสถานะเดิม

แหล่ง

เขายังพูดเหมือนกันที่อื่น

หากคุณต้องการจัดการกับพวกเขาเป็นตัวอักษรคุณสามารถ downcast พวกเขาเพื่อตัวอักษรได้ง่ายพอ ดูเหมือนจะไม่ได้เป็นกรณีการใช้งานที่สำคัญพอที่จะมีสตรีมชุดหนึ่งทั้งหมด (เหมือนกับ Short, Byte, Float)

แหล่ง

TL; DR: ไม่คุ้มกับค่าบำรุงรักษา


* ในกรณีที่คุณอยากรู้คำค้นหา google ที่ฉันใช้คือ

site:http://mail.openjdk.java.net/ charstream

2
ใครช่วยอธิบายสิ่งที่พวกเขาหมายถึงโดย100K+ of JDK footprint?
yassin

3
@yassin มีคนเขียนรหัส เขาประเมินว่าสตรีมแบบพิเศษแต่ละสายมีโค้ดมากกว่า 100,000 บรรทัด
Michael

3
@BulgarSadykov คำถามดังกล่าวเกี่ยวกับ " ทำไม X เป็นเหมือน Y " มักจะปิดตามความคิดเห็นเพราะมันเป็นไปไม่ได้ที่จะอ่านใจของผู้เขียนต้นฉบับและเว้นแต่ว่าพวกเขาจะปรากฏขึ้นทั้งหมดที่คุณจะได้รับคือการคาดเดา หากฉันถามว่า "ฉันจะส่งคำขอ POST กับไคลเอนต์ HTTP ของ Apache ได้อย่างไร" ทุกคนที่คุ้นเคยกับห้องสมุดสามารถตอบคำถามนั้นได้ เหตุใดห้องสมุดจึงได้รับการออกแบบในแบบที่เป็นไปไม่ได้ที่จะตอบ เหตุผลเดียวที่เราสามารถที่จะตอบคำถามนี้จริงๆเป็นเพราะมีการบันทึกสาธารณะของการสนทนาของพวกเขา นั่นคือสิ่งที่ฉันพยายามที่จะได้รับด้วยประโยคแรก
Michael

2
@BulgarSadykov ยังเตือนสิ่งนี้อีกด้วยกล่าวถึงบล็อกของ Eric Lippert เกี่ยวกับ C # แต่ในหัวข้อ "ทำไมฟีเจอร์ Foo ถึงไม่ได้ใช้งานในภาษา" stackoverflow.com/a/5588850/479251
Pac0

2
@BulgarSadykov ไม่เห็นด้วยอย่างเคารพ อีกครั้งฉันทำซ้ำคำถามตัวอย่างว่า " ฉันจะส่งคำขอ POST กับไคลเอนต์ HTTP ของ Apache ได้อย่างไร " คำตอบสำหรับคำถามนั้นไม่ได้เริ่มต้นด้วย " เพราะนั่นคือสิ่งที่นักออกแบบตัดสินใจ " ฉันไม่ได้เปลี่ยนถ้อยคำขอโทษ
Michael

7

ไม่ใช่เฉพาะcharอาร์เรย์ที่ไม่รองรับ

มีเพียง 3 ประเภทของลำธารดั้งเดิมมี - IntStream, และLongStreamDoubleStream

เป็นผลให้Arraysมีวิธีการที่แปลงint[], long[]และdouble[]ไปที่ลำธารดั้งเดิมที่สอดคล้องกัน

ไม่มีวิธีการที่สอดคล้องกันสำหรับการมีboolean[], byte[], short[], char[]และfloat[]ตั้งแต่เหล่านี้ชนิดดั้งเดิมไม่มีสอดคล้องลำธารดั้งเดิม


4
"เนื่องจากชนิดดั้งเดิมเหล่านี้ไม่มีกระแสดั้งเดิมที่สอดคล้องกัน" ถ้าอย่างนั้นคำถามติดตามจะเป็น "ทำไม"?
Federico klez Culloca

7
@FedericoklezCulloca ตอบคำถามติดตามที่นี่
Eran

6

charเป็นส่วนหนึ่งของString- การจัดเก็บค่า UTF-16 สัญลักษณ์ยูนิโค้ดซึ่งเป็นจุดรหัสบางครั้งก็เป็นตัวอักษรคู่แทน ดังนั้นวิธีง่ายๆที่มีตัวอักษรครอบคลุมเฉพาะส่วนหนึ่งของโดเมน Unicode

มีเวลาที่charมีสิทธิ์เป็นแบบสาธารณะ แต่ปัจจุบันมันจะดีกว่าที่จะใช้จุดรหัสIntStreamการ สตรีมของถ่านไม่สามารถจัดการกับคู่ตัวแทนได้อย่างตรงไปตรงมา

อีกเหตุผลที่น่าเป็นห่วงมากกว่าคือโมเดล "JVM" โปรเซสเซอร์ "ใช้int" register "ที่เล็กที่สุดโดยเก็บบูลีนไบต์ไบต์กางเกงขาสั้นและตัวอักษรในที่เก็บข้อมูลขนาดใหญ่ ในการที่ไม่จำเป็นต้องมีคลาสของ bloat java เราจะละเว้นการคัดลอกหนึ่งชุดที่เป็นไปได้

ในอนาคตไกลList<int>หนึ่งอาจคาดหวังชนิดดั้งเดิมได้รับอนุญาตให้ฟังก์ชั่นเป็นพารามิเตอร์ประเภททั่วไปให้ Stream<char>จากนั้นเราอาจจะเห็น

สำหรับช่วงเวลาที่ดีควรหลีกเลี่ยงcharและอาจใช้java.text.Normalizerสำหรับรหัสจุด / สตริง Unicode ในรูปแบบที่เป็นเอกลักษณ์

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.