2015-05-27 58 views
8

Günlük programımda Java 8 özelliklerini (lambda ve akışlar gibi) nasıl kullanacağımı öğrenmeye çalışıyorum çünkü daha temiz kodlar oluşturuyor.Java 8 akışları, lambdas

Şu anda üzerinde çalışıyorum: Yerel bir dosyadan bir dize akışı alıyorum, sonra da daha sonra nesnelere dönüştüğüm bazı veriler. Giriş dosyası yapısı şöyle görünür:

Airport name; Country; Continent; some number; 

Ve benim kod şöyle görünür:

:
public class AirportConsumer implements AirportAPI { 

List<Airport> airports = new ArrayList<Airport>(); 

@Override 
public Stream<Airport> getAirports() { 
    Stream<String> stream = null; 
    try { 
     stream = Files.lines(Paths.get("resources/planes.txt")); 
     stream.forEach(line -> createAirport(line)); 

    } catch (IOException e) { 
     e.printStackTrace(); 
    } 
    return airports.stream(); 
} 

public void createAirport(String line) { 
    String airport, country, continent; 
    int length; 


    airport = line.substring(0, line.indexOf(';')).trim(); 
    line = line.replace(airport + ";", ""); 
    country = line.substring(0,line.indexOf(';')).trim(); 
    line = line.replace(country + ";", ""); 
    continent = line.substring(0,line.indexOf(';')).trim(); 
    line = line.replace(continent + ";", ""); 
    length = Integer.parseInt(line.substring(0,line.indexOf(';')).trim()); 
    airports.add(new Airport(airport, country, continent, length)); 
    } 
} 

Ve benim ana sınıfında Sonuçlara nesne akışı üzerinden yineleme ve çıktısını

public class Main { 



public void toString(Airport t){ 
    System.out.println(t.getName() + " " + t.getContinent()); 
} 

public static void main(String[] args) throws IOException { 
    Main m = new Main(); 
    m.whatever(); 

} 

private void whatever() throws IOException { 
    AirportAPI k = new AirportConsumer(); 
    Stream<Airport> s; 
    s = k.getAirports(); 
    s.forEach(this::toString); 

} 


} 

Sorum şu: Bu kodu nasıl eniyileyebilirim, bu yüzden satırları ayrı ayrı dosyadan ayrıştırmak zorunda değilim, bunun yerine kaynak dosyadan düz bir şekilde nesne akışı oluşturmak zorunda kalmıyorum? Yoksa bunu yapabileceğim ölçü nedir?

+3

Not: dosyayı kapatmanız gerekir: 'try (Akım lines = Dosyalar.line (...)) {lines.map (xxx) .collect (...)};' – assylias

cevap

11

Verileri geçmişte dönüştürmek için map() kullanmanız gerekir.

Files.lines(Paths.get("resources/planes.txt")) 
    .map(line -> createAirport(line)); 

Bu Stream<Airport> dönecektir - Bir List iade etmek isterseniz, o zaman sonunda collect yöntemi kullanmak gerekir.

Bu yaklaşım aynı zamanda durum bilgisi olmayan bir durumdur; bu, örnek düzeyindeki airports değerine ihtiyacınız olmayacağı anlamına gelir.

Bir şey dönmek için createAirport yöntemini güncellemeniz gerekir:, bunu o değil createAirport bir yeniden yazmak düşünebilirsiniz

public Airport createAirport(String line) { 

    String airport = line.substring(0, line.indexOf(';')).trim(); 
    line = line.replace(airport + ";", ""); 
    String country = line.substring(0,line.indexOf(';')).trim(); 
    line = line.replace(country + ";", ""); 
    String continent = line.substring(0,line.indexOf(';')).trim(); 
    line = line.replace(continent + ";", ""); 
    int length = Integer.parseInt(line.substring(0,line.indexOf(';')).trim()); 
    return new Airport(airport, country, continent, length); 
} 

kodunuza daha işlevsel bir yaklaşım arıyorsanız çizgi değiştir. İnşaatçılar da bu tür şeyler için iyi.

public Airport createAirport(final String line) { 
    final String[] fields = line.split(";"); 
    return new Airport(fields[0].trim(), 
         fields[1].trim(), 
         fields[2].trim(), 
         Integer.parseInt(fields[3].trim())); 
} 

Hepsini bir araya getirdiğinizde, sınıfınız şimdi böyle görünüyor.

public class AirportConsumer implements AirportAPI { 

    @Override 
    public Stream<Airport> getAirports() { 
     Stream<String> stream = null; 
     try { 
      stream = Files.lines(Paths.get("resources/planes.txt")) 
            .map(line -> createAirport(line)); 
     } catch (IOException e) { 
      stream = Stream.empty(); 
      e.printStackTrace(); 
     } 
     return stream; 
    } 

    private Airport createAirport(final String line) { 
     final String[] fields = line.split(";"); 
     return new Airport(fields[0].trim(), 
          fields[1].trim(), 
          fields[2].trim(), 
          Integer.parseInt(fields[3].trim())); 
    } 
} 
+0

'CreateAirport 'yöntem, (şimdi geçersiz) listeye eklemek yerine oluşturulan havalimanını "döndürmek" olarak değiştirilir. –

+1

Ek olarak [java.util.stream] 'i (https://docs.oracle.com/javase/8/docs/api/java/util/stream/package-summary.html # package.description) paket açıklaması. Akıntıları anlamak çok uzun ve çok yararlı değil. –

+0

@tobias_k doh! Teşekkürler - sabit. –

0

Steve tarafından gönderilen kod harika görünüyor. Ama hala geliştirilebilecek iki yer var: 1, Bir dizge nasıl bölülür. 2, kullanıcıların getAirports() yöntemini çağırarak yaratılan akışı kapatmayı unuttuğunu veya bilmediğini sorun çıkarmaya neden olabilir. Yani görevi (toList() veya her neyse) yerinde bitirmek daha iyidir. İşte Try By AbacusUtil

try(Reader reader = IOUtil.createBufferedReader(file)) { 
    List<Airport> airportList = Stream.of(reader).map(line -> { 
     String[] strs = Splitter.with(";").trim(true).splitToArray(line); 
     return Airport(strs[0], strs[1], strs[2], Integer.valueOf(strs[3])); 
    }).toList(); 
} catch (IOException e) { 
    throw new RuntimeException(e); 
} 

// Veya tarafından kodudur:

List<Airport> airportList = Try.stream(file).call(s -> s.map(line -> { 
    String[] strs = Splitter.with(";").trim(true).splitToArray(line); 
    return Airport(strs[0], strs[1], strs[2], Integer.valueOf(strs[3])); 
}).toList()) 

Açıklama: Ben AbacusUtil geliştiricisi değilim.

İlgili konular