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 ? Debat 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:
-
Printah getfield digunakake kanggo njupuk variabel integer.
-
Telpon List.iterator kanggo njaluk conto iterator.
-
Telpon iterator.hasNext . Yen bali bener, cara iterator.next kudu disebut .
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: Kaya 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.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:
GO TO FULL VERSION