2015-06-07 17 views
11

Bir for döngüsü değil, lambda ifadeleri kullanarak bir sayı listesi oluşturmak istiyorum.Java'da Lambda ifadeleri 8

Yani ben formülü takip numaraları 100. Üçgen sayılar altındaki tüm üçgen numaralarının bir listesini oluşturmak istediğiniz diyelim: (n * n + n)/2

Bunu yapmanın en iyi yolu nedir ? Şu anda bu var:

Stream.iterate(1, n -> n + 1).limit(100) 
      .map(n -> (n * n + n)/2) 
      .filter(a -> a < 100) 
      .map(a -> a + "") 
      .collect(Collectors.joining(", ", "Numbers: ", ".")); 

Ama bu hesaplamaların miktarı ile gereksiz yere overkill gibi görünüyor. N'yi 1'den 100'e kadar yineliyorum (çünkü n'nin maksimum değerinin ne olduğunu bilmediğimi varsayalım), o zaman bu listenin üçgen sayı fonksiyonunu haritayorum ve sonra 100'ün altında olan sayıları kontrol ediyorum. Daha verimli bir yol var mı Bunu yaparken? Ayrıca: Yineleme, sınırlama ve ardından harita kullanmak yerine Aktarımın yalnızca yineleme işlevini kullanarak üçgen sayılarını oluşturabilir miyim?

DÜZENLEME: Demek ki ana nokta şudur: Üçgen sayılarından biri 100'ü aştığı anda traingle sayılarının hesaplanması nasıl durur? Genellikle bu gibi yazmak istiyorum:

çok verimli olan en kısa sürede bir üçgen sayısı 100 aşıyor olarak durur
ArrayList<Integer> triangles = new ArrayList<>(); 
for (int n=1;true;n++) { 
    int num = (n*n+n)/2; 

    if (num>100) break; 

    triangles.add(num); 
} 

; lambda ifadesinde bu etkinliği nasıl koruyabilirim?

+2

Stream.iterate (1, n-> n + 1) .limit (100) 'muhtemelen daha okunaklı olan IntStream.rangeClosed (1, 100) olarak yeniden yazılabilir. – Pshemo

+0

neden hem limit hem de filtre kullanıyorsunuz?İkinci filtrenin çıktıyı hesaplamaya göre sınırlayacağına inanıyorum, bu yüzden 100'den daha az olan girdiler yerine 100'den daha az olan sonuçlar elde edersiniz. –

+0

Konu nedir? Yoksa sadece merak mı? – doublep

cevap

6

Genel olarak baktığınız şey, almaktır. Ne yazık ki, Java 8 akışlarında varsayılan bir uygulaması yoktur. Bir question about take-while'a bakın.

+3

Java 9 için çalışılıyor olsa da. –

-2

Yapmak istediğiniz tek şey verilen sırayı üçgene dönüştürmenizdir (açıkladığınız gibi), bu çok daha basit.

List<Integer> l = IntStream.rangeClosed(1, 100) 
      .mapToObj(n -> (n*n + n)/2) 
      .collect(Collectors.toList()); 

ilkel akış sarma

, nesnelere dolayısıyla mapToObj yöntemi dönüştürmek kadar ilave bir adım gereklidir.

Eğer 100 vurduğunda filtreleme durdurmak için arıyorsanız, aklıma gelen en kolay yolu

IntFunction<Integer> calc =n -> (n*n+n)/2; 
    List<Integer> l = IntStream.rangeClosed(1, 100) 
      .filter(n -> calc.apply(n) < 100) 
      .mapToObj(calc) 
      .collect(Collectors.toList()); 

Sorunuzun değişikliklere dayanarak, bu işaret etmek de oldukça önemli olduğunu düşünüyorum olduğunu. Eğer yapmak için kullanılan ne yansıtmak istiyorsanız, bu şu şekilde görünecektir:

List<Integer> results = new ArrayList<>(100); 
    IntStream.rangeClosed(1, 100).forEach(i -> { 
     int tri =calc.apply(i); 
     if(tri < 100) { 
      results.add(tri); 
     } 
    }); 

O (varsayılan uygulama yineleyici aşağıdaki gerçi) akışlar mutlaka sipariş olmadığını belirtmekte fayda var. Eğer bu paralel bir akıma dönüştürülmüş olsaydı, farkı (ve akımların gücü) görürdünüz. Yürütme emrinden kaçamazsınız, çünkü işleme emri hakkında belirli bir tutarı varsayıyorsunuz. Erken filtreleyerek (ikinci formumda), son hesaplamadan önce yalnızca 13 girdiden oluşan sonuç akışıyla sonuçlandığınızdan emin olursunuz. Bu paralel seçeneği bir not olarak da alın.

List<Integer> l = IntStream.rangeClosed(1, 100).parallel() 
      .filter(n -> calc.apply(n) < 100) 
      .mapToObj(calc) 
      .collect(Collectors.toList()); 

Hala sipariş edildiğini göreceksiniz, ancak bunların hesaplaması birden çok iş parçacığı üzerinde yapıldı.

+1

OP, (n * n + n)/2 'değeri, filtrelenmesi gereken vakaların yüksekliğinden dolayı 100'den daha büyük olmaya başladığında akışının nasıl durdurulacağını soruyor. Öyleyse soru şu ki "eğer bazı n-inci değerlerden sonra değerlere ihtiyaç duyulmayacaksa, onları nasıl atlayabiliriz". – Pshemo

+0

Op henüz hiç soru cevaplamıyor. Henüz ne istediğini açık değil. –

+3

@JohnAment Eğer sorunun ne olduğu belli değilse, bu cevap vermemek için iyi bir neden. –

İlgili konular