如何按 2 个字段对对象进行排序 Java
How to Sort objects by 2 fields Java
我正在尝试读取的文件如下所示:
1995 Pokemon Ikue Ôtani
1940 Tom and Jerry William Hanna
1995 Pokemon voice actor2
1940 Tom and Jerry voice actor3
2000 Cartoon voice actor
它有大约 20k 行。我已经读取文件并将数据存储在一个对象中。
in = new BufferedReader(new FileReader(cartoonsFile));
ArrayList<String> voiceActors = new ArrayList<>();
ArrayList<Cartoon> cartoons = new ArrayList<>();
//read each line
String line = in.readLine();
while (line != null) {
String[] columns = line.split("\t");
String year = columns[0];
String cartoon = columns[1];
String voiceActor = columns[2];
//make new object and store data
Cartoon c = new Cartoon(Integer.parseInt(columns[0]),
columns[1], columns[2]));
cartoons.add(c); //add to the array list
对象
public class Cartoon {
private int year;
private String title;
private String voiceActor;
public Cartoon(int year, String title, String voiceActor) {
this.year = year;
this.title = title;
this.voiceActor = voiceActor;
}
};
我想在线程中读取文件并按年份排序。任何人都可以提供有关如何同时实现多线程和归并排序的示例代码吗?
我想要得到的输出
1940 Tom and Jerry William Hanna
voice actor2
voice actor3
voice actor4
voice actor5
1995 Pokemon Ikue Ôtani
voice actor2
A Cartoon voice actor1
voice actor2
voice actor3
2000 Cartoon voice actor
试试这个。
List<CartoonYear> readAndSortByYear(String inFile) throws IOException {
return Files.readAllLines(Paths.get(inFile))
.parallelStream()
.map(line -> line.split("\t"))
.map(columns -> new CartoonYear(Integer.parseInt(columns[0]), columns[1], columns[2]))
.sorted(Comparator.comparing(CartoonYear::getYear))
.collect(Collectors.toList());
}
坚持你的数据结构(只是将它从相当奇特的 CartoonYear
重命名为 Cartoon
),并坚持使用 @saka1029 使用 Java 流的好方法(而不是手动实现合并排序算法),你可以这样做:
package org.acme;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
public class Cartoon {
private int year;
private String title;
private String voiceActor;
public Cartoon(int year, String title, String voiceActor) {
this.year = year;
this.title = title;
this.voiceActor = voiceActor;
}
public static Map<String, List<Cartoon>> readAndGroupByYearAndTitle(String inFile) throws IOException {
return Files.readAllLines(Paths.get(inFile))
.parallelStream()
.map(line -> line.split("\t"))
.map(columns -> new Cartoon(Integer.parseInt(columns[0]), columns[1], columns[2]))
.collect(Collectors.groupingBy(cartoon -> String.format("%4d %s", cartoon.year, cartoon.title)));
}
public static void main(String[] args) throws IOException {
Map<String, List<Cartoon>> cartoonsGrouped = readAndGroupByYearAndTitle(args[0]);
cartoonsGrouped.keySet()
.parallelStream()
.sorted()
.forEachOrdered(group -> {
boolean firstElement = true;
for (Cartoon cartoonYear : cartoonsGrouped.get(group)) {
if (firstElement) {
System.out.printf("%4d %-25s %s%n", cartoonYear.year, cartoonYear.title, cartoonYear.voiceActor);
firstElement = false;
}
else
System.out.printf("%4s %-25s %s%n", "", "", cartoonYear.voiceActor);
}
});
}
}
这只是又快又脏,不是我引以为豪的代码。您要求每组只打印一次年份和标题,也不会使 if-else
的代码更好。但假设您有这样的输入文件:
1995 Pokemon Ikue Ôtani
1940 Tom and Jerry William Hanna
11 Sample foo
1995 Pokemon voice actor2
1940 Tom and Jerry voice actor3
2000 Cartoon voice actor
11 Sample bar
你会得到这样的输出:
11 Sample foo
bar
1940 Tom and Jerry William Hanna
voice actor3
1995 Pokemon Ikue Ôtani
voice actor2
2000 Cartoon voice actor
我正在尝试读取的文件如下所示:
1995 Pokemon Ikue Ôtani
1940 Tom and Jerry William Hanna
1995 Pokemon voice actor2
1940 Tom and Jerry voice actor3
2000 Cartoon voice actor
它有大约 20k 行。我已经读取文件并将数据存储在一个对象中。
in = new BufferedReader(new FileReader(cartoonsFile));
ArrayList<String> voiceActors = new ArrayList<>();
ArrayList<Cartoon> cartoons = new ArrayList<>();
//read each line
String line = in.readLine();
while (line != null) {
String[] columns = line.split("\t");
String year = columns[0];
String cartoon = columns[1];
String voiceActor = columns[2];
//make new object and store data
Cartoon c = new Cartoon(Integer.parseInt(columns[0]),
columns[1], columns[2]));
cartoons.add(c); //add to the array list
对象
public class Cartoon {
private int year;
private String title;
private String voiceActor;
public Cartoon(int year, String title, String voiceActor) {
this.year = year;
this.title = title;
this.voiceActor = voiceActor;
}
};
我想在线程中读取文件并按年份排序。任何人都可以提供有关如何同时实现多线程和归并排序的示例代码吗?
我想要得到的输出
1940 Tom and Jerry William Hanna
voice actor2
voice actor3
voice actor4
voice actor5
1995 Pokemon Ikue Ôtani
voice actor2
A Cartoon voice actor1
voice actor2
voice actor3
2000 Cartoon voice actor
试试这个。
List<CartoonYear> readAndSortByYear(String inFile) throws IOException {
return Files.readAllLines(Paths.get(inFile))
.parallelStream()
.map(line -> line.split("\t"))
.map(columns -> new CartoonYear(Integer.parseInt(columns[0]), columns[1], columns[2]))
.sorted(Comparator.comparing(CartoonYear::getYear))
.collect(Collectors.toList());
}
坚持你的数据结构(只是将它从相当奇特的 CartoonYear
重命名为 Cartoon
),并坚持使用 @saka1029 使用 Java 流的好方法(而不是手动实现合并排序算法),你可以这样做:
package org.acme;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
public class Cartoon {
private int year;
private String title;
private String voiceActor;
public Cartoon(int year, String title, String voiceActor) {
this.year = year;
this.title = title;
this.voiceActor = voiceActor;
}
public static Map<String, List<Cartoon>> readAndGroupByYearAndTitle(String inFile) throws IOException {
return Files.readAllLines(Paths.get(inFile))
.parallelStream()
.map(line -> line.split("\t"))
.map(columns -> new Cartoon(Integer.parseInt(columns[0]), columns[1], columns[2]))
.collect(Collectors.groupingBy(cartoon -> String.format("%4d %s", cartoon.year, cartoon.title)));
}
public static void main(String[] args) throws IOException {
Map<String, List<Cartoon>> cartoonsGrouped = readAndGroupByYearAndTitle(args[0]);
cartoonsGrouped.keySet()
.parallelStream()
.sorted()
.forEachOrdered(group -> {
boolean firstElement = true;
for (Cartoon cartoonYear : cartoonsGrouped.get(group)) {
if (firstElement) {
System.out.printf("%4d %-25s %s%n", cartoonYear.year, cartoonYear.title, cartoonYear.voiceActor);
firstElement = false;
}
else
System.out.printf("%4s %-25s %s%n", "", "", cartoonYear.voiceActor);
}
});
}
}
这只是又快又脏,不是我引以为豪的代码。您要求每组只打印一次年份和标题,也不会使 if-else
的代码更好。但假设您有这样的输入文件:
1995 Pokemon Ikue Ôtani
1940 Tom and Jerry William Hanna
11 Sample foo
1995 Pokemon voice actor2
1940 Tom and Jerry voice actor3
2000 Cartoon voice actor
11 Sample bar
你会得到这样的输出:
11 Sample foo
bar
1940 Tom and Jerry William Hanna
voice actor3
1995 Pokemon Ikue Ôtani
voice actor2
2000 Cartoon voice actor