2016-03-28 28 views
4

Java-8 akışları kullanmak için bu (basitleştirilmiş) kodu çevirmek çalışıyorum: Buradaakışları kullanarak koşullu bir harita doldurma - Java 8

Map<String, String> files = new ConcurrentHashMap<String, String>(); 

while(((line = reader.readLine()) != null) { 
     if(content != null) 
     files.put("not null"+line, "not null"+line); 
     else 
     files.put("its null"+line, "its null"+line); 
    } 
reader.close(); 

denedim budur:

files = reader.lines().parallel().collect((content != null)? 
       (Collectors.toConcurrentMap(line->"notnull"+line, line->line+"notnull")) :            
       (Collectors.toConcurrentMap(line->line+"null", line->line+"null"))); 

Ancak, yukarıdakiler, intelliJ'deki tüm line->line+"..." için "döngüsel çıkarım" mesajını verir. Döngüsel çıkarım nedir? Bu mantıkta bir hata var mı?

SO ile ilgili bazı benzer sorunlara dikkat çektim. Ancak, uygulamaları yerine arayüz (Harita) kullanmayı önerirler. Ancak files burada Map olarak bildirilmiştir.

Güncelleştirme: Daha fazla bağlam ekleme, content dizinin adını tutan bir dizedir. files, birden çok dosya yolunu tutan bir haritadır. files haritasına gitmek için hangi dosya yollarına gitmek gerekiyor content dizin adına kayıtlı veya değil.

+1

Kod örneği biraz belirsiz. (1) "İçerik" değişkeni nedir? (2) Tek bir dosyanın satırlarını mı okuyorsunuz, yoksa onları "dosya" olarak adlandırılan bir haritaya mı koyuyorsunuz? –

+1

1. 'content', bir dizinin adını tutan bir String'dir. 2.Evet, bir metin dosyasından satırları okuyorum (temelde bazı kısmi belirteçler içerir) ve bunları birlikte dosya haritasına girecek dosya yollarına ekliyorum. – AshwiniR

cevap

7

Bu sorunu çözmek için başka bir yol kollektör için ara değişkenini tanıtmaktır: ara diziler tahsis değildir (@JanXMarek tarafından sunulan bir farklı)

Collector<String, ?, ConcurrentMap<String, String>> collector = (content != null) ? 
     (Collectors.toConcurrentMap(line->"notnull"+line, line->line+"notnull")) : 
     (Collectors.toConcurrentMap(line->line+"null", line->line+"null")); 
Map<String, String> files = reader.lines().parallel().collect(collector);  

Bu çözüm, her giriş hattı content kontrol etmez . Döngüsel çıkarım, iç alt-ekspresyonun türünü belirlemek için tip çıkarım prosedüründeki durumdur, dış alt-ekspresyonun tipi belirlenmelidir, fakat iç alt-ekspresyonun türünü bilmeden belirlenemez. Java-8'deki çıkarımı yaz, Stream<String>.collect(Collectors.toConcurrentMap(line->line+"null", line->line+"null")) durumunda, Toplayıcı türünün Collector<String, ?, ConcurrentMap<String, String>> olduğunu çıkartabilir. Normalde alt-ifade tipi (burada toConcurrentMap(...) alt ifadesi hakkında konuşuyoruz) açık bir şekilde belirlenemez, dış bağlam metot çağırma, döküm veya atama ise dış bağlam kullanılarak azaltılabilir. Bununla birlikte, dış bağlam, kendi karmaşık tür çıkarım kurallarına sahip olan ?: operatördür, bu yüzden bu çok fazla olur ve açık türünü bir yerde belirten tür çıkarım sistemine yardımcı olmalısınız.

+0

Dinamik olarak çok fazla bellek ayırmadığınız için bu çözümün daha okunabilir ve verimli olduğunu düşünüyorum. –

+0

Bu çözümü beğendim, ancak üçlü operatörü 'keyMapper' ve' valueMapper' işlev tanımlarına taşıyacaktım ve 'Collectors.toConcurrentMap' –

4

Sen, bu

reader.lines().parallel() 
    .map(line -> content == null ? 
      new String[]{"notnull"+line, line+"notnull"} : 
      new String[]{line+"null", line+"null"}) 
    .collect(Collectors.toConcurrentMap(pair -> pair[0], pair -> pair[1])); 

Birinci gibi yapabiliriz sen haritası bir (anahtar, değer) satır bir dizi saklanan çifti (veya Çifti nesne çeşit), sonra kollektörde tekrar bir anahtar ve bir değere ayırırsınız.

+0

Teşekkürler @Jan. Çiftin bir String dizisi olduğunu nasıl bilebilirdi? Bunu toConcurrentMap() 'içinde bildirmeliyim? .map() 'in dize dizisini "pair" değişkenine iletmesi gerektiğini düşünüyorum, ancak tanımlanmayan bir hata alıyorum. – AshwiniR

+1

Üzgünüz, kodumda bir yazım hatası çözdüm. Ancak, herhangi bir yerde türü bildirmeniz gerekmez. Java derleyicisi, harita() işleminin sonucundan onu şişirir. Kodumu kopyalayıp yapıştırabilir ve çalışmalıdır ("okuyucu" ve "içerik" değişkenleri tanımlandığı sürece). Değilse, tam olarak hangi hatayı alıyorsunuz? –

+0

Döngüsel çıkarımın ne olduğunu hala merak ediyorum. Herkes biraz ışık tutabilir. – AshwiniR

1

Sadece bir yan not. Bu bağlamda .parallel() herhangi bir iyi olduğundan şüpheliyim. Dosyaları okumak için standart Java API'sini kullanıyorsanız, alttaki yineleyici, dosyayı sırayla okuyacaktır. Paralel olarak yürütülecek tek şey çizgileri dönüştürecek. Sadece PC'mde merakımdan çıktım ve .parallel() olmadan yaklaşık% 10 daha hızlıydı.

Paralelleştirme, işlemin, akımın girişini okumaktan daha büyük bir yavaşlama sırası olması durumunda anlamlıdır, ki buradaki durum böyle değildir.

+0

Merhaba Jan' da bunları kullanacaktım. parallel() '+' toConcurrentMap() 'kombinasyonu paralel olmayan +' toMap() 'kombinasyonuna karşı? ve paralel olmayan + toMap() öğesinin daha hızlı çalıştığını gördünüz mü? – AshwiniR

+0

I Paralel olarak ConcurrentMap'e paralel olmayan ve giriş yaklaşık 100K satırlık bir dosyaydu. Eh, farklı bir donanım veya işletim sistemi üzerinde farklı davranabilir. Belki bu durumda sisteminizde paralellikle% 10'luk bir kazanç elde edersiniz. Benim amacım, .parallell() özgür bir bira değildi. 8 çekirdekli bir işlemciniz olsa bile, gerçek durumların% 93.73547'sine paralel olarak, her zaman başka bir yerde bulunan Ahmdal yasasına göre, daha iyi davranmayacaktır. –