简体   繁体   English

无法弄清楚如何以正确的顺序打印列表

[英]Can't figure out how to print a list in this correct order

Basically I have an arraylist of objects which have a name and startDate and they are in a similar initial order to : 基本上,我有一个对象的数组列表,这些对象具有名称和startDate,并且它们的初始顺序类似于:

Frank 10/20/1990 弗兰克1990年10月20日

Bill 1/2/1990 1990年1月2日的法案

Frank 2/2/1990 弗兰克2/2/1990

John 9/8/1990 约翰1990年9月8日

Bill 4/4/1990 1990年4月4日法案

Frank 5/1/1990 弗兰克1990年5月1日

I'm trying to print them in order of the first names declared and then by date, eg, the final printing should print : 我试图按声明的名字顺序打印,然后按日期打印,例如,最终打印应打印:

Frank 1/1/1990 弗兰克1990年1月1日

Frank 5/1/1990 弗兰克1990年5月1日

Frank 10/20/1990 弗兰克1990年10月20日

Bill 1/2/1990 1990年1月2日的法案

Bill 4/4/1990 1990年4月4日法案

John 9/8/1990 约翰1990年9月8日

Assuming you object class looks like this: 假设您的对象类如下所示:

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;
  }
}

You could print your objects using the following method: 您可以使用以下方法打印对象:

@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);
}

Output: 输出:

Bill Tue Jan 02 00:00:00 CET 1990 1990年1月2日星期二00:00:00 CET
Bill Wed Apr 04 00:00:00 CEST 1990 1990年4月4日星期三00:00:00比尔
Frank Fri Feb 02 00:00:00 CET 1990 1990年2月2日星期五星期五欧洲中部时间
Frank Tue May 01 00:00:00 CEST 1990 1990年5月1日美国东部时间00:00:00
Frank Sat Oct 20 00:00:00 CET 1990 1990年10月20日星期六星期六09:00:00 CET
John Sat Sep 08 00:00:00 CEST 1990 John Sat 1990年9月8日00:00:00


This uses Java 8 streams and a comparator chain to sort your objects. 它使用Java 8流和比较器链对对象进行排序。 The comparators compare by a given attribute, the thenComparing is used to chain them. 比较器按给定的属性进行比较, thenComparing使用thenComparing链接它们。


UPDATE: 更新:

As I am not sure if I possibly misunderstood you, here is a second version for the following case: 由于不确定我是否可能误解了您,因此以下情况的第二个版本:

You want to sort by name, but in the order the names are appearing in the original list , so names first appearing will be first. 您想按名称排序,但是名称会按顺序出现在原始列表中 ,因此名称将首先出现。

In this case you will have to remember the order of the names in a separate, temporary list (only containing the unique names in the original order) that can be used inside the comparator afterwards. 在这种情况下,您将必须记住一个单独的临时列表中的名称顺序(仅按原始顺序包含唯一名称),之后可以在比较器中使用它们。

This list is produced by transforming the original list into a set (so have only the unique names) and then transforming this set back into a list (to be able to use indexOf inside the comparator). 通过将原始列表转换为一个集合(因此只有唯一的名称),然后将该集合转换回一个列表(以便能够在比较器中使用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);
}

Output: 输出:

Frank Fri Feb 02 00:00:00 CET 1990 1990年2月2日星期五星期五欧洲中部时间
Frank Tue May 01 00:00:00 CEST 1990 1990年5月1日美国东部时间00:00:00
Frank Sat Oct 20 00:00:00 CET 1990 1990年10月20日星期六星期六09:00:00 CET
Bill Tue Jan 02 00:00:00 CET 1990 1990年1月2日星期二00:00:00 CET
Bill Wed Apr 04 00:00:00 CEST 1990 1990年4月4日星期三00:00:00比尔
John Sat Sep 08 00:00:00 CEST 1990 John Sat 1990年9月8日00:00:00

You should do it in two steps: 您应该分两个步骤进行操作:

First order by name using custom comparator like: 使用自定义比较器按名称排序,例如:

    Collections.sort(myList, new Comparator<MyObject>() {
       public int compare(MyObject o1, MyObject o2) {
          return o1.getName().compareTo(o2.getName());
       }
    });

And store the output in a temp list 并将输出存储在临时列表中

Second use temp list to sort by data: 第二次使用临时列表按数据排序:

    Collections.sort(myList, new Comparator<MyObject>() {
       public int compare(MyObject o1, MyObject o2) {
           return o1.getDate().compareTo(o2.getDate());
       }
    });

then your list will be sorted as you want. 然后您的列表将按照您的意愿进行排序。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM