Java 8流,lambdas

Ven*_*aey 9 java lambda java-8 java-stream

我正在尝试学习如何在我的日常编程中使用Java 8功能(例如lambdas和流),因为它使代码更清晰.

以下是我目前正在处理的内容:我从本地文件中获取一个字符串流,其中包含一些数据,稍后我将这些数据转换为对象.输入文件结构如下所示:

Airport name; Country; Continent; some number;
Run Code Online (Sandbox Code Playgroud)

我的代码看起来像这样:

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));
    }
}
Run Code Online (Sandbox Code Playgroud)

在我的主类中,我遍历对象流并打印出结果:

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

}


}
Run Code Online (Sandbox Code Playgroud)

我的问题是:如何优化此代码,因此我不必单独解析文件中的行,而是直接从源文件创建Airport对象流?或者这是我能做到这一点的程度?

Ste*_*ner 12

您需要使用它map()来转换数据.

Files.lines(Paths.get("resources/planes.txt"))
     .map(line -> createAirport(line));
Run Code Online (Sandbox Code Playgroud)

这将返回Stream<Airport>- 如果你想返回a List,那么你需要collect在最后使用该方法.

这种方法也是无状态的,这意味着您不需要实例级airports值.

您需要更新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);
}
Run Code Online (Sandbox Code Playgroud)

如果您正在寻找一种更具功能性的代码方法,您可能需要考虑重写,createAirport这样就不会改变行.建筑商也很喜欢这种东西.

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()));
}
Run Code Online (Sandbox Code Playgroud)

把它们放在一起,你的班级现在看起来像这样.

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()));
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 但这不是流的工作方式.所有中间操作都是惰性的,并且当接收器(也称为终端操作)需要另一个元素时执行.因此,最后一行将在终端操作处理最后一个元素之前"映射"到"机场"实例(如果它曾经这样做,因为它可能是短路的).因此,没有任何地方已经转换过所有行,但保持流开放是有意义的. (5认同)
  • 你的`try(...)`语句将在返回之前关闭流,这肯定不是你想要的.try-with-resources构造仅对您在语句范围内处理的资源有用,而不是在您希望将资源返回给方法的调用者时.顺便说一句,我不明白你为什么要命名一个*生产*`Airport`实例`AirportConsumer`的类. (3认同)