2015-09-02 15 views
12

Bir koleksiyon nesnesi üzerinde yinelemek istediğimi varsayalım.Lambda İfadeleri ve Anonim Sınıflar arasındaki uygulama farklılıkları/en iyileştirmeler

List<String> strmap = ... 
//Without lambdas 
strmap.stream().filter(new Predicate<String>() { 
     public boolean test(String string) { 
      return string.length == 10; 
     } 
}.forEach(new Consumer<String>() { 
     public void accept (String string) { 
      System.out.println("string " + string + " contains exactly 10 characters"); 
     } 
} 
//With lambdas 
strmap.stream() 
     .filter(s -> s.length == 10) 
     .forEach(s -> System.out.println("string " + s + " contains exactly 10 characters"); 

İkinci örnek (lambdas olmadan) nasıl çalışır? Kodu çağırdığım her seferde yeni bir nesne (Predicate and Consumer) oluşturuldu, java jit derleyicisi lambda ifadesini ne kadar ideal hale getirebilir? Daha iyi bir performans için tüm lambdaları bir değişken olarak ilan etmeli ve her zaman sadece bir referans mı vermeliyim?

private Predicate<String> length10 = s -> s.length == 10; 
private Consumer<String> printer = s -> { "string " + s + " contains exactly 10 characters"; } 

strmap.stream() 
     .filter(length10) 
     .forEach(printer); 
+3

Bkz. (Burada) (http://stackoverflow.com/q/27524445/2711488). Ve [this] (http://stackoverflow.com/a/23991339/2711488) lambda ifadeleri ve yöntem referansları için de geçerlidir. HotSpot, iç sınıfların geçici örneklerini en iyi duruma getirebilir, ancak vatansız lambda ifadeleri için ilk etapta geçici örnekler yoktur. – Holger

+1

@Holger - güzel yanıtlar – ZhongYu

cevap

6

Nasıl (lambdas olmadan) ikinci örnek çalışır? Kodu çağırdığım her seferde yeni bir nesne (Predicate and Consumer) oluşturuldu, java jit derleyicisi lambda ifadesini ne kadar ideal hale getirebilir? Daha iyi bir performans için tüm lambdaları bir değişken olarak ilan etmeli ve her zaman sadece bir referans mı vermeliyim?

JIT'in işi, bunu yapmak için endişelenmenize gerek kalmamasıdır. Örneğin, JIT, s -> s.length == 10'un otomatik olarak statik bir sabit hale gelmesi için (ve, inanıyorum) bunu yapabilir, bu yüzden sadece bu örnek için değil, tüm sınıf boyunca yeniden kullanılır. Başka bir yerde aynı lambda kullanan diğer sınıflarda bile yeniden kullanılabilir.

Tüm lambda noktası, sadece mantıklı olan en basit kodu yazmanız ve JIT'in bu kadar verimli olması için gereken her şeyi yapma özgürlüğüne sahip olmanızdır. Örneğin, bu yüzden lambdalar, ilk etapta anonim iç sınıflara basitçe yalpalamak yerine invokedynamic kullanılarak üretilir.

Doğrudan kodu yazın; Doğru şeyi yapmak için JIT'ye güven. İşte bunun için var. Yani, ezici, karmaşık nitty-cesur ayrıntıları istiyorsanız, this neredeyse kesinlikle en iyi kaynaktır.

+3

's.length() == 10' değişmez olduğundan, JIT’in yardımına ihtiyaç duymadan her zaman sabit olur. [Bu] (http://stackoverflow.com/q/27524445/2711488) bile yorumlanmış mod için geçerlidir… – Holger

+0

Uygulamayı belirten bağlantılı dokümanı okuyorum. AFAICT, s -> s.length() == 10', özel bir statik yönteme indirgenmiştir, ancak JIT'in, arabirim örneğine nasıl dönüştürüleceğine karar veren lambda metafactory'yi uyguladığı izlenimi altındayım. –

+2

Hayır, ['LambdaMetafactory'] (http://docs.oracle.com/javase/8/docs/api/?java/lang/invoke/LambdaMetafactory.html) kuyu kullanarak bayt kodu üreten sıradan bir Java sınıfıdır. tanınan ASM kütüphanesi. Bir lambda ifadesi ilk kez başlatıldığında bir Java hata ayıklayıcısı kullanarak bu adımı bile geçebilirsiniz. Ancak, 'invokedynamic' komutunun nasıl çalıştığı nedeniyle, sonraki infazlar, sabit veya fabrika metodu/kurucu çağrısına bir sap olan ilk girişin sonucunu kullanacaktır. – Holger

İlgili konular