JavaRush /จาวาบล็อก /Random-TH /คอฟฟี่เบรค #137. For loop หรือ Foreach - อันไหนเร็วกว่าใน...

คอฟฟี่เบรค #137. For loop หรือ Foreach - อันไหนเร็วกว่าใน Java? 8 วิธีที่มีประสิทธิภาพในการวนซ้ำแต่ละรายการในแผนที่ Java

เผยแพร่ในกลุ่ม

For loop หรือ Foreach - อันไหนเร็วกว่าใน Java?

ที่มา: ปานกลาง เมื่อฉันกำลังมองหางานเมื่อสองสามปีที่แล้ว หนึ่งในคำถามที่ฉันถูกถามในการสัมภาษณ์คือเราควรวนซ้ำ ArrayList โดยใช้forหรือforEach ? คอฟฟี่เบรค #137.  For loop หรือ Foreach - อันไหนเร็วกว่าใน Java?  8 วิธีที่มีประสิทธิภาพในการวนซ้ำแต่ละรายการในแผนที่ Java - 1การถกเถียงเกี่ยวกับความแตกต่างในการตั้งค่าระหว่างforEachและforมีมานานแล้ว ฉันรู้สึกว่าforEachเร็วกว่า แต่สุดท้ายฉันก็รู้ว่าฉันคิดผิด โปรดทราบว่าforEach loop (หรือปรับปรุงสำหรับ loop ) ที่นำมาใช้ใน Java 1.5 ช่วยลดความยุ่งเหยิงและโอกาสที่จะเกิดข้อผิดพลาดโดยการซ่อนตัววนซ้ำหรือตัวแปรดัชนีทั้งหมด ฉันเชื่อว่าข้อแตกต่างในทางปฏิบัติเพียงอย่างเดียวระหว่างforและforEachคือในกรณีของอ็อบเจ็กต์ที่มีการจัดทำดัชนี เราไม่สามารถเข้าถึงดัชนีได้
for(int i = 0; i < mylist.length; i++) {
 if(i < 5) {
 //do something
 } else {
 //do other stuff
 }
}
อย่างไรก็ตาม เราสามารถสร้างตัวแปรดัชนีแยกต่างหากประเภทint โดยใช้forEach ตัวอย่างเช่น:
int index = -1;
for(int myint : mylist) {
 index++;
 if(index < 5) {
 //do something
 } else {
 //do other stuff
 }
}
มาเขียนคลาสง่ายๆ ที่มี เมธอด foreachTest ( )ที่วนซ้ำรายการโดยใช้forEach
import java.util.List;

public class ForEachTest {
	List<Integer> intList;

    public void foreachTest(){
        for(Integer i : intList){

        }
    }
}
เมื่อเราคอมไพล์คลาสนี้ คอมไพเลอร์จะแปลงโค้ดเป็นการภายในให้เป็นการใช้งานตัววนซ้ำ ฉันถอดรหัสโค้ดที่คอมไพล์แล้วโดยการรันjavap -verbose IterateListTest
public void foreachTest();
   descriptor: ()V
   flags: ACC_PUBLIC
   Code:
     stack=1, locals=3, args_size=1
        0: aload_0
        1: getfield      #19                 // Field intList:Ljava/util/List;
        4: invokeinterface #21,  1           // InterfaceMethod java/util/List.iterator:()Ljava/util/Iterator;
        9: astore_2
       10: goto          23
       13: aload_2
       14: invokeinterface #27,  1           // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
       19: checkcast     #33                 // class java/lang/Integer
       22: astore_1
       23: aload_2
       24: invokeinterface #35,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
       29: ifne          13
       32: return
     LineNumberTable:
       line 9: 0
       line 12: 32
     LocalVariableTable:
       Start  Length  Slot  Name   Signature
           0      33     0  this   Lcom/greekykhs/springboot/ForEachTest;
     StackMapTable: number_of_entries = 2
       frame_type = 255 /* full_frame */
         offset_delta = 13
         locals = [ class com/greekykhs/springboot/ForEachTest, top, class java/util/Iterator ]
         stack = []
       frame_type = 9 /* same */
จากโค้ดไบต์ด้านบนเราจะเห็น:
  1. คำสั่งgetfieldใช้เพื่อรับตัวแปรจำนวนเต็ม

  2. โทรList.iteratorเพื่อรับอินสแตนซ์ตัววนซ้ำ

  3. เรียกiterator.hasNext _ หากคืนค่าเป็นจริงควร เรียกเมธอด iterator.next

มาทำการทดสอบประสิทธิภาพกัน ใน เมธอดIterateListTest หลัก ฉันได้สร้างรายการและวนซ้ำโดยใช้for และ forEach loops
import java.util.ArrayList;
import java.util.List;

public class IterateListTest {
	public static void main(String[] args) {
		List<Integer> mylist = new ArrayList<>();
        for (int i = 0; i < 1000000; i++) {
            mylist.add(i);
        }

        long forLoopStartTime = System.currentTimeMillis();
        for (int i = 0; i < mylist.size(); i++) {mylist.get(i);}

        long forLoopTraversalCost =System.currentTimeMillis()-forLoopStartTime;
        System.out.println("for loop traversal cost for ArrayList= "+ forLoopTraversalCost);

        long forEachStartTime = System.currentTimeMillis();
        for (Integer integer : mylist) {}

        long forEachTraversalCost =System.currentTimeMillis()-forEachStartTime;
        System.out.println("foreach traversal cost for ArrayList= "+ forEachTraversalCost);
	}
}
และนี่คือผลลัพธ์: คอฟฟี่เบรค #137.  For loop หรือ Foreach - อันไหนเร็วกว่าใน Java?  8 วิธีที่มีประสิทธิภาพในการวนซ้ำแต่ละรายการในแผนที่ Java - 2ดังที่เราเห็นแล้วว่าประสิทธิภาพของfor loop นั้นดีกว่าforEach loop หากคุณใช้LinkedListแทนArrayListคุณจะเห็นว่า ประสิทธิภาพ forEachนั้น ดีกว่าสำหรับLinkedList ArrayListใช้อาร์เรย์ภายในเพื่อจัดเก็บองค์ประกอบ เนื่องจากอาร์เรย์เป็นพื้นที่ที่อยู่ติดกันของหน่วยความจำ ความซับซ้อนของเวลาจึงเป็น O(1) เนื่องจากข้อมูลถูกดึงผ่านดัชนี LinkedListใช้รายการที่เชื่อมโยงแบบทวีคูณ เมื่อเราใช้for loop เพื่อใช้การสำรวจเส้นทาง มันจะเริ่มต้นจากโหนดหลักของรายการที่เชื่อมโยงในแต่ละครั้ง ดังนั้นความซับซ้อนของเวลาคือ O(n*n)

8 วิธีที่มีประสิทธิภาพในการวนซ้ำแต่ละรายการในแผนที่ Java

ที่มา: ปานกลาง เมื่อสัปดาห์ที่แล้ว มีเด็กฝึกงานถามฉันว่าจะทำซ้ำ Java Map ได้อย่างไร ฉันตอบว่าเนื่องจากมันง่ายมาก คำตอบสำหรับคำถามนี้จึงอยู่ใน Google เสมอ หลังจากนั้นไม่นาน เธอก็ส่งที่อยู่ของหน้า StackOverflow มาให้ฉัน และปรากฎว่ามีผู้คนจำนวนมากให้ความสนใจกับปัญหานี้ ดังนั้นฉันจึงตัดสินใจที่จะพูดถึงประเด็นของการวนซ้ำและแบ่งปันวิธีการต่างๆ กับคุณ คอฟฟี่เบรค #137.  For loop หรือ Foreach - อันไหนเร็วกว่าใน Java?  8 วิธีที่มีประสิทธิภาพในการวนซ้ำแต่ละรายการในแผนที่ Java - 3

1. การใช้ตัววนซ้ำและ Map.Entry

@Test
public void test1_UsingWhileAndMapEntry(){
    long i = 0;
    Iterator<Map.Entry<Integer, Integer>> it = map.entrySet().iterator();
    while (it.hasNext()) {
        Map.Entry<Integer, Integer> pair = it.next();
        i += pair.getKey() + pair.getValue();
    }
    System.out.println(i);
}

2. การใช้ foreach และ Map.Entry

@Test
public void test2_UsingForEachAndMapEntry(){
    long i = 0;
    for (Map.Entry<Integer, Integer> pair : map.entrySet()) {
        i += pair.getKey() + pair.getValue();
    }
    System.out.println(i);
}

3. การใช้ foreach จาก Java 8

@Test
public void test3_UsingForEachAndJava8(){
    final long[] i = {0};
    map.forEach((k, v) -> i[0] += k + v);
    System.out.println(i[0]);
}

4. การใช้ชุดคีย์และ foreach

@Test
public void test4_UsingKeySetAndForEach(){
    long i = 0;
    for (Integer key : map.keySet()) {
        i += key + map.get(key);
    }
    System.out.println(i);
}

5. การใช้ชุดคีย์และตัววนซ้ำ

@Test
public void test5_UsingKeySetAndIterator(){
    long i = 0;
    Iterator<Integer> it = map.keySet().iterator();
    while (it.hasNext()) {
        Integer key = it.next();
        i += key + map.get(key);
    }
    System.out.println(i);
}

6. การใช้ for และ Map.Entry

@Test
public void test6_UsingForAndIterator(){
    long i = 0;
    for (Iterator<Map.Entry<Integer, Integer>> entries = map.entrySet().iterator(); entries.hasNext(); ) {
        Map.Entry<Integer, Integer> entry = entries.next();
        i += entry.getKey() + entry.getValue();
    }
    System.out.println(i);
}

7. การใช้ Java 8 สตรีม API

@Test
public void test7_UsingJava8StreamApi(){
    System. out .println(map.entrySet().stream().mapToLong(e -> e.getKey() + e.getValue()).sum());
}

8. การใช้ Java 8 Stream API แบบขนาน

@Test
public void test8_UsingJava8StreamApiParallel(){
    System. out .println(map.entrySet().parallelStream().mapToLong(e -> e.getKey() + e.getValue()).sum());
}

เปรียบเทียบแต่ละวิธีในแง่ของความเร็ว:

public final static Integer SIZE = 1000000;
public Map<Integer, Integer> map = toMap();
public Map<Integer, Integer> toMap(){
    map = new HashMap<>(SIZE);
    for (int i = 0; i < SIZE; i++) {
        map.put(i, i);
    }
    return map;
}
เราได้รับ: คอฟฟี่เบรค #137.  For loop หรือ Foreach - อันไหนเร็วกว่าใน Java?  8 วิธีที่มีประสิทธิภาพในการวนซ้ำแต่ละรายการในแผนที่ Java - 4คอฟฟี่เบรค #137.  For loop หรือ Foreach - อันไหนเร็วกว่าใน Java?  8 วิธีที่มีประสิทธิภาพในการวนซ้ำแต่ละรายการในแผนที่ Java - 5คอฟฟี่เบรค #137.  For loop หรือ Foreach - อันไหนเร็วกว่าใน Java?  8 วิธีที่มีประสิทธิภาพในการวนซ้ำแต่ละรายการในแผนที่ Java - 6

บทสรุป

จากการเปรียบเทียบข้อมูล เราได้เรียนรู้ว่าวิธีที่ 6 ใช้เวลามากที่สุด และวิธีที่ 8 ใช้เวลามากที่สุดเมื่อมีตัวเลขน้อย แต่ใช้เวลาน้อยที่สุดเมื่อตัวเลขมีนัยสำคัญ เนื่องจากวิธีที่ 8 ดำเนินการพร้อมกัน สิ่งที่น่าสนใจคือลำดับการดำเนินการทดสอบนั้นมีไว้สำหรับ -> ในขณะที่ -> foreach/stream เสมอ และฉันไม่รู้ว่าทำไม :(
ความคิดเห็น
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION