Java 8 个流,lambda
Java 8 streams, lambdas
我正在尝试学习如何在我的日常编程中利用 Java 8 个功能(例如 lambda 和流),因为它可以使代码更简洁。
这是我目前正在做的事情:
我从本地文件中获取了一个字符串流,其中包含一些数据,稍后我将这些数据转换为对象。输入文件结构如下所示:
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));
}
}
在我的主要 class 中,我遍历对象流并打印出结果:
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);
}
}
我的问题是:如何优化这段代码,这样我就不必单独解析文件中的行,而是直接从源文件中创建对象流 Airport?或者这是我能做到的程度?
您需要使用 map()
来转换数据。
Files.lines(Paths.get("resources/planes.txt"))
.map(line -> createAirport(line));
这将 return 一个 Stream<Airport>
- 如果你想 return 一个 List
,那么你需要使用 collect
方法结束。
这种方法也是无状态的,这意味着您不需要实例级 airports
值。
您需要将 createAirport 方法更新为 return 某些内容:
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);
}
如果您正在寻找一种更实用的代码方法,您可能需要考虑重写 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()));
}
将它们放在一起,您的 class 现在看起来像这样。
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()));
}
}
Steve 发布的代码看起来不错。但是还有两个地方可以改进:
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 的开发者。
我正在尝试学习如何在我的日常编程中利用 Java 8 个功能(例如 lambda 和流),因为它可以使代码更简洁。
这是我目前正在做的事情: 我从本地文件中获取了一个字符串流,其中包含一些数据,稍后我将这些数据转换为对象。输入文件结构如下所示:
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));
}
}
在我的主要 class 中,我遍历对象流并打印出结果:
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);
}
}
我的问题是:如何优化这段代码,这样我就不必单独解析文件中的行,而是直接从源文件中创建对象流 Airport?或者这是我能做到的程度?
您需要使用 map()
来转换数据。
Files.lines(Paths.get("resources/planes.txt"))
.map(line -> createAirport(line));
这将 return 一个 Stream<Airport>
- 如果你想 return 一个 List
,那么你需要使用 collect
方法结束。
这种方法也是无状态的,这意味着您不需要实例级 airports
值。
您需要将 createAirport 方法更新为 return 某些内容:
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);
}
如果您正在寻找一种更实用的代码方法,您可能需要考虑重写 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()));
}
将它们放在一起,您的 class 现在看起来像这样。
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()));
}
}
Steve 发布的代码看起来不错。但是还有两个地方可以改进: 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 的开发者。