基本上我有一个具有name和startDate的对象的arraylist,它们的初始顺序类似于:
Frank 10/20/1990
Bill 1/2/1990
Frank 2/2/1990
John 9/8/1990
Bill 4/4/1990
Frank 5/1/1990
我正在尝试按照声明的名字顺序打印它们,然后按日期打印,例如,应打印最终打印:
Frank 1/1/1990
Frank 5/1/1990
Frank 10/20/1990
Bill 1/2/1990
Bill 4/4/1990
John 9/8/1990
答案 0 :(得分:1)
假设您的对象类看起来像这样:
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年 Bill Wed Apr 04 00:00:00 CEST 1990
Frank Fri Feb 02 00:00:00 CET 1990年 Frank Tue May 01 00:00:00 CEST 1990
Frank Sat Oct 20 00:00:00 CET 1990年 John Sat Sep 08 00:00:00 CEST 1990
这使用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);
}
输出:
Frank Fri Feb 02 00:00:00 CET 1990年 Frank Tue May 01 00:00:00 CEST 1990
Frank Sat Oct 20 00:00:00 CET 1990年 Bill Tue Jan 02 00:00:00 CET 1990年 Bill Wed Apr 04 00:00:00 CEST 1990
John Sat Sep 08 00:00:00 CEST 1990
答案 1 :(得分:0)
您应该分两步完成:
首先使用自定义比较器按名称命令,如:
Collections.sort(myList, new Comparator<MyObject>() {
public int compare(MyObject o1, MyObject o2) {
return o1.getName().compareTo(o2.getName());
}
});
并将输出存储在临时列表中
第二次使用临时列表按数据排序:
Collections.sort(myList, new Comparator<MyObject>() {
public int compare(MyObject o1, MyObject o2) {
return o1.getDate().compareTo(o2.getDate());
}
});
然后您的列表将按您的要求排序。