Collection.stream (). filter (). forEach () ไม่มีประสิทธิภาพเปรียบเทียบกับมาตรฐานสำหรับแต่ละลูปหรือไม่


15

IntelliJ IDEA แนะนำให้ฉันตอนนี้เพื่อแทนที่ลูปสำหรับแต่ละลูปต่อไปนี้ด้วยการเรียก Java 8 "forEach":

    for (Object o : objects) {
        if (o instanceof SomeObject) {
            doSomething();
        }
    }

การโทรที่แนะนำจะเป็นเช่นนี้:

objects.stream().filter(o -> o instanceof SomeObject).forEach(o -> doSomething());

เว้นแต่ว่าฉันเข้าใจผิดว่าฟังก์ชันการทำงานพื้นฐานของ Stream ทำงานอย่างไรฉันดูเหมือนว่าการใช้ stream เป็นการดำเนินการ O (2n) ซึ่งตรงข้ามกับการดำเนินการ O (n) สำหรับมาตรฐานสำหรับแต่ละลูป


8
ทำไมคุณถึงคิดว่ามันเป็น O ^ 2 ในความเป็นจริงลำธารถูกประดิษฐ์ขึ้นเป็นพิเศษเพื่อ (a) อนุญาตไวยากรณ์ดีกว่าและ (b) ไม่แนะนำค่าใช้จ่ายเพิ่มเติม (ที่จริงแล้วพวกเขามักจะลดค่าใช้จ่ายผ่านการประเมินผลที่ขี้เกียจ)
Kilian Foth

ตามไวยากรณ์ดูเหมือนว่าเป็นครั้งแรกที่วนซ้ำในการกรองแล้ววนซ้ำวัตถุที่ถูกกรองในครั้งที่สองเพื่อเรียกใช้รหัสของฉัน
Mirrana

6
แม้ว่ามันจะทำเช่นนั้นก็จะยังคงเป็น O (2 * N) ซึ่งก็คือ O (N) นั่นคือเชิงเส้นและไม่เป็นกำลังสอง แต่ที่จริงแล้วการวนซ้ำนั้นเกิดขึ้นพร้อมกันและทั้งคู่อาจยุติลงเร็วกว่าปกติหากทราบผลแล้ว - นั่นคือความงามของลำธาร แน่นอนว่ามันคุ้มค่าที่จะใช้เวลา 15 นาทีในการอ่านสตรีมใน Java 8 ดังที่ Venkat Subramaniam เขียนว่า '' การแสดงออกของแลมบ์ดาเป็นยาเสพติดที่ประตูสู่ Java 8 แต่ลำธารเป็นสิ่งเสพติดที่แท้จริง ''
Kilian Foth

1
นอกจากนี้: ห่วงของคุณเป็น antipattern;)
โทมัสจังค์

1
@ThomasJunk คุณช่วยอธิบายได้อย่างไรว่ามันเป็นปฏิปักษ์? ฉันไม่คุ้นเคยกับอันนี้
Mirrana

คำตอบ:


21

สตรีม Java ไม่วนซ้ำผ่านคอลเลกชันของคุณหนึ่งครั้งสำหรับแต่ละข้อความสั่งแม้ว่าจะมีความหมายตามไวยากรณ์ มันใช้ห่วงโซ่ทั้งหมดกับแต่ละองค์ประกอบหนึ่งองค์ประกอบในเวลา

ในกรณีของคุณสตรีมจะทำงานเหมือนกับวนรอบ ใช้องค์ประกอบตรวจสอบกับเพรดิเคตของคุณจากนั้นใช้การดำเนินการของคุณจากนั้นไปยังองค์ประกอบถัดไป

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