คำตอบนี้เกี่ยวข้องกับประสิทธิภาพของการนำลูปไปใช้งานต่าง ๆ มันเกี่ยวข้องเพียงเล็กน้อยสำหรับลูปที่เรียกว่า VERY OFTEN (เช่นการโทรนับล้านครั้ง) ในกรณีส่วนใหญ่เนื้อหาของลูปจะเป็นองค์ประกอบที่มีราคาแพงที่สุด สำหรับสถานการณ์ที่คุณวนซ้ำบ่อยครั้งสิ่งนี้อาจเป็นที่สนใจ
คุณควรทำซ้ำการทดสอบนี้ภายใต้ระบบเป้าหมายเพราะนี่คือการใช้งานเฉพาะ ( รหัสที่มาแบบเต็ม )
ฉันใช้ openjdk รุ่น 1.8.0_111 บนเครื่องลีนุกซ์ที่เร็ว
ฉันเขียนการทดสอบที่วนรอบ 10 ^ 6 ครั้งในรายการโดยใช้รหัสนี้ด้วยขนาดที่แตกต่างกันสำหรับintegers
(10 ^ 0 -> 10 ^ 5 รายการ)
ผลลัพธ์อยู่ด้านล่างวิธีที่เร็วที่สุดจะแตกต่างกันไปขึ้นอยู่กับปริมาณของรายการในรายการ
แต่ยังอยู่ในสถานการณ์ที่เลวร้ายที่สุดการวนซ้ำ 10 ^ 5 รายการ 10 ^ 6 ครั้งใช้เวลา 100 วินาทีสำหรับนักแสดงที่แย่ที่สุดดังนั้นข้อควรพิจารณาอื่น ๆ จึงมีความสำคัญมากกว่าในทุกสถานการณ์
public int outside = 0;
private void forCounter(List<Integer> integers) {
for(int ii = 0; ii < integers.size(); ii++) {
Integer next = integers.get(ii);
outside = next*next;
}
}
private void forEach(List<Integer> integers) {
for(Integer next : integers) {
outside = next * next;
}
}
private void iteratorForEach(List<Integer> integers) {
integers.forEach((ii) -> {
outside = ii*ii;
});
}
private void iteratorStream(List<Integer> integers) {
integers.stream().forEach((ii) -> {
outside = ii*ii;
});
}
นี่คือการกำหนดเวลาของฉัน: มิลลิวินาที / ฟังก์ชั่น / จำนวนรายการในรายการ การวิ่งแต่ละครั้งคือ 10 ^ 6 ลูป
1 10 100 1000 10000
iterator.forEach 27 116 959 8832 88958
for:each 53 171 1262 11164 111005
for with index 39 112 920 8577 89212
iterable.stream.forEach 255 324 1030 8519 88419
ถ้าคุณทำซ้ำการทดลองที่ผมโพสต์รหัสที่มาเต็ม โปรดแก้ไขคำตอบนี้และเพิ่มผลลัพธ์ด้วยเครื่องหมายของระบบที่ผ่านการทดสอบ
ใช้ MacBook Pro, 2.5 GHz Intel Core i7, 16 GB, macOS 10.12.6:
1 10 100 1000 10000
iterator.forEach 27 106 1047 8516 88044
for:each 46 143 1182 10548 101925
for with index 49 145 887 7614 81130
iterable.stream.forEach 393 397 1108 8908 88361
Java 8 Hotspot VM - 3.4GHz Intel Xeon, 8 GB, Windows 10 Pro
1 10 100 1000 10000
iterator.forEach 30 115 928 8384 85911
for:each 40 125 1166 10804 108006
for with index 30 120 956 8247 81116
iterable.stream.forEach 260 237 1020 8401 84883
Java 11 Hotspot VM - 3.4GHz Intel Xeon, 8 GB, Windows 10 Pro
(เครื่องเดียวกันกับรุ่น JDK ที่ต่างกัน)
1 10 100 1000 10000
iterator.forEach 20 104 940 8350 88918
for:each 50 140 991 8497 89873
for with index 37 140 945 8646 90402
iterable.stream.forEach 200 270 1054 8558 87449
Java 11 OpenJ9 VM - 3.4GHz Intel Xeon, 8 GB, Windows 10 Pro
(เครื่องเดียวกันและรุ่น JDK ข้างต้น, VM ที่แตกต่างกัน)
1 10 100 1000 10000
iterator.forEach 211 475 3499 33631 336108
for:each 200 375 2793 27249 272590
for with index 384 467 2718 26036 261408
iterable.stream.forEach 515 714 3096 26320 262786
Java 8 Hotspot VM - 2.8GHz AMD, 64 GB, Windows Server 2016
1 10 100 1000 10000
iterator.forEach 95 192 2076 19269 198519
for:each 157 224 2492 25466 248494
for with index 140 368 2084 22294 207092
iterable.stream.forEach 946 687 2206 21697 238457
Java 11 Hotspot VM - 2.8GHz AMD, 64 GB, Windows Server 2016
(เครื่องเดียวกันข้างต้น, เวอร์ชั่น JDK ที่แตกต่างกัน)
1 10 100 1000 10000
iterator.forEach 72 269 1972 23157 229445
for:each 192 376 2114 24389 233544
for with index 165 424 2123 20853 220356
iterable.stream.forEach 921 660 2194 23840 204817
Java 11 OpenJ9 VM - 2.8GHz AMD, 64 GB, Windows Server 2016
(เครื่องเดียวกันและรุ่น JDK ข้างต้น, VM ที่แตกต่างกัน)
1 10 100 1000 10000
iterator.forEach 592 914 7232 59062 529497
for:each 477 1576 14706 129724 1190001
for with index 893 838 7265 74045 842927
iterable.stream.forEach 1359 1782 11869 104427 958584
การติดตั้ง VM ที่คุณเลือกสร้างความแตกต่าง Hotspot / OpenJ9 / etc
Iterable.forEach takes the collection's lock
. ข้อมูลนี้มาจากไหน? ฉันไม่พบพฤติกรรมดังกล่าวในแหล่งข้อมูล JDK