说明
假设您有一个文件,其中包含如下行
John:Doe:20:USA
Jane:Doe:35:Germany
Robert:Moe:14:Japan
Larry:Loe:25:China
Richard:Roe:27:India
你想要年龄最高的 3 行,那就是
Jane:Doe:35:Germany
Richard:Roe:27:India
Larry:Loe:25:China
程序很简单。首先读取所有行,用: 分割,然后将数据解析到像Person 这样的包装类中。将它们收集到像List<Person> 这样的集合中,并使用比较年龄的Comparator 对它们进行排序。或者,您可以让Person 实现Comparable,然后使用它们的自然顺序。
如果效率很重要,您也可以进行部分排序,因为您只对前 3 个匹配项感兴趣。为此,您可以使用PriorityQueue,插入所有元素并调用poll 三次。
解决方案
首先是Person 包装类
public class Person {
private String mFirstName;
private String mSurname;
private int mAge;
private String mCountry;
public Person(String firstName, String surname, int age, String country) {
this.mFirstName = firstName;
this.mSurname = surname;
this.mAge = age;
this.mCountry = country;
}
// TODO Some getters
public String toString() {
return this.mFirstName + ":" + this.mSurname
+ ":" + this.mAge + ":" + this.mCountry;
}
public static Person parse(String[] data) {
String firstName = data[0];
String surname = data[1];
int age = Integer.parseInt(data[2]);
String country = data[3];
return new Person(firstName, surname, age, country);
}
}
接下来我们读取所有行,拆分数据并将它们解析为Person。之后,我们对结果进行排序并将结果限制为3。最后我们收集到List 并打印结果。
Path file = Paths.get(...);
Pattern separator = Pattern.compile(":");
List<Person> persons = Files.lines(file) // Stream<String>
.map(separator::splitAsStream) // Stream<String[]>
.map(Person::parse) // Stream<Person>
.sorted(Comparator.comparingInt(Person::getAge).reversed())
.limit(3)
.collect(Collectors.toList());
persons.forEach(System.out::println);
或者如果您想按照建议使用PriorityQueue,这将改善运行时间:
Path file = Paths.get(...);
Pattern separator = Pattern.compile(":");
PriorityQueue<Person> personQueue = Files.lines(file)
.map(separator::splitAsStream)
.map(Person::parse)
.collect(Collectors.toCollection(() -> {
return new PriorityQueue<>(
Comparator.comparingInt(Person::getAge).reversed());
}));
List<Person> persons = new ArrayList<>(3);
persons.add(personQueue.poll());
persons.add(personQueue.poll());
persons.add(personQueue.poll());
persons.forEach(System.out::println);