基本上,我有一个对象的数组列表,这些对象具有名称和startDate,并且它们的初始顺序类似于:
弗兰克1990年10月20日
1990年1月2日的法案
弗兰克2/2/1990
约翰1990年9月8日
1990年4月4日法案
弗兰克1990年5月1日
我想按声明的名字顺序打印,然后按日期打印,例如,最终打印应打印:
弗兰克1990年1月1日
弗兰克1990年5月1日
弗兰克1990年10月20日
1990年1月2日的法案
1990年4月4日法案
约翰1990年9月8日
最佳答案
假设您的对象类如下所示:
private static class MyObject {
private final String name;
private final Date date;
private MyObject(String name, Date date) {
this.name = name;
this.date = date;
}
public String getName() {
return name;
}
public Date getDate() {
return date;
}
}
您可以使用以下方法打印对象:
@Test
public void printInOrder() {
List<MyObject> list = new ArrayList<>(); // List containing your objects
list.add(new MyObject("Frank", Date.from(LocalDate.of(1990, 10, 20).atStartOfDay(ZoneId.systemDefault()).toInstant())));
list.add(new MyObject("Bill", Date.from(LocalDate.of(1990, 1, 2).atStartOfDay(ZoneId.systemDefault()).toInstant())));
list.add(new MyObject("Frank", Date.from(LocalDate.of(1990, 2, 2).atStartOfDay(ZoneId.systemDefault()).toInstant())));
list.add(new MyObject("John", Date.from(LocalDate.of(1990, 9, 8).atStartOfDay(ZoneId.systemDefault()).toInstant())));
list.add(new MyObject("Bill", Date.from(LocalDate.of(1990, 4, 4).atStartOfDay(ZoneId.systemDefault()).toInstant())));
list.add(new MyObject("Frank", Date.from(LocalDate.of(1990, 5, 1).atStartOfDay(ZoneId.systemDefault()).toInstant())));
list.stream()
.sorted(Comparator.comparing(MyObject::getName)
.thenComparing(Comparator.comparing(MyObject::getDate)))
.map(obj -> obj.getName() + " " + obj.getDate())
.forEach(System.out::println);
}
输出:
Bill Tue Jan 02 00:00:00 CET 1990
1990年4月4日星期三00:00:00比尔
1990年2月2日星期五星期五欧洲中部时间
1990年5月1日星期二美国东部时间弗兰克(Frank Tue)
1990年10月20日,星期六ET CET
John Sat 1990年9月8日00:00:00
它使用Java 8流和比较器链对对象进行排序。比较器按给定属性进行比较,
thenComparing
用于链接它们。更新:
由于不确定我是否可能误解了您,因此以下是以下情况的第二种版本:
您想按名称排序,但是名称会按顺序出现在原始列表中,因此名称将首先出现。
在这种情况下,您将必须记住一个单独的临时列表中的名称顺序(仅按原始顺序包含唯一名称),之后可以在比较器中使用它们。
通过将原始列表转换为一个集合(因此只有唯一的名称),然后将此集合转换回一个列表(以便能够在比较器中使用
indexOf
)来生成此列表。@Test
public void printInOrder() {
List<MyObject> list = new ArrayList<>();
list.add(new MyObject("Frank", Date.from(LocalDate.of(1990, 10, 20).atStartOfDay(ZoneId.systemDefault()).toInstant())));
list.add(new MyObject("Bill", Date.from(LocalDate.of(1990, 1, 2).atStartOfDay(ZoneId.systemDefault()).toInstant())));
list.add(new MyObject("Frank", Date.from(LocalDate.of(1990, 2, 2).atStartOfDay(ZoneId.systemDefault()).toInstant())));
list.add(new MyObject("John", Date.from(LocalDate.of(1990, 9, 8).atStartOfDay(ZoneId.systemDefault()).toInstant())));
list.add(new MyObject("Bill", Date.from(LocalDate.of(1990, 4, 4).atStartOfDay(ZoneId.systemDefault()).toInstant())));
list.add(new MyObject("Frank", Date.from(LocalDate.of(1990, 5, 1).atStartOfDay(ZoneId.systemDefault()).toInstant())));
List<String> declaredNameOrder = new ArrayList<>(list.stream()
.map(MyObject::getName)
.collect(Collectors.toCollection(LinkedHashSet::new)));
list.stream()
.sorted(Comparator.<MyObject>comparingInt(o -> declaredNameOrder.indexOf(o.getName()))
.thenComparing(Comparator.comparing(MyObject::getDate)))
.map(obj -> obj.getName() + " " + obj.getDate())
.forEach(System.out::println);
}
输出:
1990年2月2日星期五星期五欧洲中部时间
1990年5月1日星期二美国东部时间弗兰克(Frank Tue)
1990年10月20日,星期六ET CET
Bill Tue Jan 02 00:00:00 CET 1990
1990年4月4日星期三00:00:00比尔
John Sat 1990年9月8日00:00:00