2015-09-11 32 views
10

staram się wykonać wszystkie zadania 100 równolegle przez wykonawców i runnable, zadanie musi użyć zmiennej pętli:użyciu zmiennej pętli niebędącej ostatecznej wewnątrz wyrażenia lambda

for (int i = 0; i < 100; i++) { 
    executor.execute(() -> { 
    doSomething(String.format("Need task number %d done", i)); 
    } 
    }); 
} 

dostaję falowane pod "I" powiedzenie - Variable used in lambda expression should be effectively final.

Zmienna pętli, o ile mi wiadomo, nie może być ostateczna ani efektywna, ponieważ jest zmieniana przy każdej iteracji. Znalazłem proste obejście,

for (int i = 0; i < 100; i++) { 
    int index = i; 
    executor.execute(() -> { 
    doSomething(String.format("Need task number %d done", index)); 
    } 
}); 
} 

to nie wydaje się najbardziej skuteczne rozwiązanie dla mnie, ogłaszając nową zmienną przy każdej iteracji. Czy jest lepszy sposób na zrobienie tego?

+0

Jest to zmienna lokalna, więc myślę, że tak naprawdę nie ma znaczenia – ka4eli

+0

@ ka4eli - zgodził się. Pod względem wydajności nie ma znaczenia. JVM najprawdopodobniej po prostu ją usunie i użyje 'i' bezpośrednio. Skuteczne, końcowe wymaganie jest egzekwowane tylko przez javac, ze względu na programistów. Runtime po prostu przechwytuje bieżącą wartość. – ZhongYu

+0

@ bayou.io bardzo interesujące, nie myślałem o optymalizacji JVM. – Siddhartha

Odpowiedz

12

Czy jest lepszy sposób to zrobić?

Wątpię w to. Twoje rozwiązanie wygląda dobrze dla mnie, ale jeśli chcesz, możesz przerobić go na ewentualnie wyraźniejszego kodzie jak:

IntStream.range(0, 100).forEach(
    i -> executor.execute(
     () -> doSomething(String.format("Need task number %d done", i)) 
    ) 
); 
+0

To jest zwięzłe i doskonałe. Użyję tego. Dziękuję bardzo. – Siddhartha

2

To najprostszy sposób, aby to zadziałało. Nie zrobisz tego lepiej.

+2

zgadzam się. chyba że mielibyśmy użytek 'Iterable ' - 'for (int i: range (0, 100))' - tutaj 'i' byłoby efektywne. – ZhongYu