2015-05-27 30 views
8

मैं अपने दैनिक प्रोग्रामिंग में जावा 8 फीचर्स (जैसे लैम्ब्डा और स्ट्रीम) का उपयोग कैसे करना सीखता हूं, क्योंकि यह बहुत साफ कोड बनाता है।जावा 8 स्ट्रीम, लैम्बडास

यहां मैं वर्तमान में काम कर रहा हूं: मुझे स्थानीय फाइल से एक स्ट्रिंग स्ट्रीम मिलती है जिसमें कुछ डेटा हैं जो मैं बाद में ऑब्जेक्ट्स में बदल जाता हूं। इनपुट फ़ाइल संरचना इस तरह दिखता है:

Airport name; Country; Continent; some number; 

और मेरे कोड इस तरह दिखता है:

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)); 
    } 
} 

और अपने मुख्य वर्ग में मैं वस्तु स्ट्रीम पर पुनरावृति और परिणाम प्रिंट आउट:

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); 

} 


} 

मेरा प्रश्न यह है: मैं इस कोड को कैसे अनुकूलित कर सकता हूं, इसलिए मुझे फ़ाइल से लाइनों को अलग से पार्स करने की ज़रूरत नहीं है, बल्कि इसके बजाय स्रोत फ़ाइल से सीधे ऑब्जेक्ट्स की स्ट्रीम बनाएं? या यह वह सीमा है जिसमें मैं यह कर सकता हूं?

+3

नोट: आपको फ़ाइल बंद करनी चाहिए: 'कोशिश करें (स्ट्रीम लाइनें = Files.lines (...)) {lines.map (xxx) .collect (...)}; ' – assylias

उत्तर

11

डेटा को बदलने के लिए आपको map() का उपयोग करने की आवश्यकता है जैसा कि यह अतीत आता है।

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

यह एक Stream<Airport> वापस आ जाएगी - यदि आप एक List वापस करना चाहते हैं, तो आप अंत में collect विधि का उपयोग करने की आवश्यकता होगी।

यह दृष्टिकोण भी स्टेटलेस है, जिसका अर्थ है कि आपको आवृत्ति-स्तर airports मान की आवश्यकता नहीं होगी।

आप अपने createAirport विधि को अपडेट करने के लिए कुछ वापस जाने के लिए की आवश्यकता होगी:, आप में से createAirport तो यह नहीं करता है एक पुनर्लेखन विचार कर सकते हैं

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); 
} 

आप अपने कोड के लिए एक अधिक कार्यात्मक दृष्टिकोण के लिए देख रहे हैं लाइन बदलना नहीं है। बिल्डर्स इस तरह की चीज़ के लिए भी अच्छे हैं।

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())); 
} 

इसे सभी को एक साथ फेंकना, आपकी कक्षा अब इस तरह दिखती है।

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 'विधि को उस समय (अब अप्रचलित) सूची में जोड़ने के बजाय बनाए गए हवाई अड्डे को 'वापसी' करने के लिए बदल दिया गया है। –

+1

एक अतिरिक्त के रूप में मैं [java.util.stream] (https://docs.oracle] को पढ़ने की सिफारिश करता हूं।कॉम/जावाज़/8/डॉक्स/एपीआई/जावा/यूज/स्ट्रीम/पैकेज-सारांश.html # पैकेज डिस्क्रिप्शन) पैकेज विवरण। यह धाराओं को समझने में बहुत लंबा और वास्तव में सहायक नहीं है। –

+0

@tobias_k doh! धन्यवाद - तय है। –

0

स्टीव द्वारा पोस्ट किया गया कोड बहुत अच्छा लगता है। लेकिन अभी भी दो स्थानों में सुधार किया जा सकता है: 1, स्ट्रिंग को कैसे विभाजित करें। 2, अगर लोग getAirports() विधि को कॉल करके बनाई गई स्ट्रीम को बंद करने के बारे में भूल जाते हैं या नहीं जानते हैं तो यह समस्या हो सकती है। इसलिए कार्य को पूरा करना बेहतर है (toList() या जो भी हो)। यहाँ 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); 
} 

// या द्वारा कोड है Try द्वारा:

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()) 

प्रकटीकरण: मैं AbacusUtil के डेवलपर हूं।

संबंधित मुद्दे