JavaRush /Blog Jawa /Random-JV /Ngopi #137. Kanggo loop utawa Foreach - endi sing luwih c...

Ngopi #137. Kanggo loop utawa Foreach - endi sing luwih cepet ing Jawa? 8 Cara Efisien kanggo Loop liwat Saben Entri ing Peta Jawa

Diterbitake ing grup

Kanggo loop utawa Foreach - endi sing luwih cepet ing Jawa?

Sumber: Sedheng Nalika aku nggoleki proyek sawetara taun kepungkur, salah sawijining pitakonan sing ditakoni ing wawancara yaiku apa kita kudu ngulang ArrayList nggunakake for utawa forEach ? Ngopi #137.  Kanggo loop utawa Foreach - endi sing luwih cepet ing Jawa?  8 Cara Efisien kanggo Loop Saben Entri ing Peta Jawa - 1Debat babagan prabédan ing preferensi antarane forEach lan for wis suwe banget. Aku ana ing roso kesengsem sing forEach luwih cepet. Nanging pungkasane aku sadar yen aku salah. FYI, loop forEach (utawa ditingkatake kanggo loop ) sing dienal ing Jawa 1.5 ngilangi keruwetan lan kemungkinan kesalahan kanthi ndhelikake iterator utawa variabel indeks kabeh. Aku pracaya mung prabédan praktis antarane for lan forEach yaiku ing kasus obyek sing diindeks, kita ora duwe akses menyang indeks.
for(int i = 0; i < mylist.length; i++) {
 if(i < 5) {
 //do something
 } else {
 //do other stuff
 }
}
Nanging, kita bisa nggawe variabel indeks kapisah saka jinis int nggunakake forEach . Tuladhane:
int index = -1;
for(int myint : mylist) {
 index++;
 if(index < 5) {
 //do something
 } else {
 //do other stuff
 }
}
Ayo dadi nulis kelas prasaja sing wis foreachTest () cara sing iterates liwat dhaftar nggunakake forEach .
import java.util.List;

public class ForEachTest {
	List<Integer> intList;

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

        }
    }
}
Nalika kita ngumpulake kelas iki, compiler internal ngowahi kode menyang implementasine iterator. Aku decompiled kode kompilasi dening mbukak 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 */
Saka bytecode ing ndhuwur kita ndeleng:
  1. Printah getfield digunakake kanggo njupuk variabel integer.

  2. Telpon List.iterator kanggo njaluk conto iterator.

  3. Telpon iterator.hasNext . Yen bali bener, cara iterator.next kudu disebut .

Ayo padha nindakake tes kinerja. Ing metode IterateListTest utama , aku nggawe dhaptar lan diulang kanthi nggunakake for lan forEach puteran .
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);
	}
}
Lan iki asile: Ngopi #137.  Kanggo loop utawa Foreach - endi sing luwih cepet ing Jawa?  8 Cara Efisien kanggo Nguterake Saben Entri ing Peta Jawa - 2Kaya sing kita deleng, kinerja for loop luwih apik tinimbang forEach loop . Yen sampeyan nggunakake LinkedList tinimbang ArrayList , sampeyan bisa ndeleng manawa forEach kinerja luwih apik kanggo LinkedList . ArrayList internal nggunakake array kanggo nyimpen unsur. Amarga array minangka wilayah memori sing cedhak, kompleksitas wektu yaiku O (1). Iki amarga data dijupuk liwat indeks. LinkedList nggunakake dhaptar sing disambung kaping pindho. Nalika kita nggunakake for daur ulang kanggo ngleksanakake traversal, iku wiwit saka simpul sirah dhaftar disambung saben wektu, supaya kerumitan wektu O (n * n).

8 Cara Efisien kanggo Loop liwat Saben Entri ing Peta Jawa

Sumber: Sedheng Minggu kepungkur, ana intern takon kepiye carane ngulang Peta Jawa. Aku mangsuli amarga iku prasaja banget, jawaban kanggo pitakonan iki tansah ing Google. Sawise sawetara wektu, dheweke ngirim alamat kaca ing StackOverflow, lan ternyata akeh wong sing nggatekake masalah iki. Mulane, aku mutusake kanggo mikir babagan masalah pengulangan lan nuduhake sawetara cara kanggo nindakake karo sampeyan. Ngopi #137.  Kanggo loop utawa Foreach - endi sing luwih cepet ing Jawa?  8 Cara Efisien kanggo Nguterake Saben Entri ing Peta Jawa - 3

1. Nggunakake iterator lan 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. Nggunakake foreach lan 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. Nggunakake foreach saka basa Jawa 8

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

4. Nggunakake keySet lan foreach

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

5. Nggunakake keySet lan iterator

@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. Nggunakake kanggo lan 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. Nggunakake Java 8 Stream API

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

8. Paralel nggunakake Java 8 Stream API

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

Perbandingan saben cara ing babagan kacepetan:

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;
}
Kita entuk: Ngopi #137.  Kanggo loop utawa Foreach - endi sing luwih cepet ing Jawa?  8 Cara Efisien kanggo Loop Saben Entri ing Peta Jawa - 4Ngopi #137.  Kanggo loop utawa Foreach - endi sing luwih cepet ing Jawa?  8 Cara Efisien kanggo Nguterake Saben Entri ing Peta Jawa - 5Ngopi #137.  Kanggo loop utawa Foreach - endi sing luwih cepet ing Jawa?  8 Cara Efisien kanggo Nguterake Saben Entri ing Peta Jawa - 6

Kesimpulan

Saka mbandhingake data, kita sinau yen cara 6 njupuk wektu paling akeh lan cara 8 njupuk wektu paling akeh nalika nomer cilik, nanging njupuk wektu paling sethithik nalika nomer penting amarga cara 8 dieksekusi bebarengan. Sing menarik yaiku urutan eksekusi tes tansah kanggo -> while -> foreach/stream lan aku ora ngerti kenapa :(
Komentar
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION