【问题标题】:Sorting a number of lists based on two lists in Java基于Java中的两个列表对多个列表进行排序
【发布时间】:2022-01-24 21:26:12
【问题描述】:

我有四个列表如下:

    ArrayList<String> tempNameList = new ArrayList<>();
    ArrayList<String> tempPhoneList = new ArrayList<>();
    ArrayList<String> tempAddressList = new ArrayList<>();
    ArrayList<String> tempBirthdayList = new ArrayList<>();

每个列表都包含按索引与其他列表相关的记录。我正在尝试按人的姓名和生日升序对所有列表进行排序。我试过使用Collections.sort(),但它一次只支持一个列表。
如何按姓名和生日对所有列表进行排序?

【问题讨论】:

  • 你考虑过使用类吗?
  • @shmosel 你的意思是使用 List 吗?
  • 我的意思是List&lt;Person&gt;,其中class Person 包含字段namephoneaddressbirthday
  • @shmosel 我还没有尝试过。我的代码是使用列表完成的。如何使用类对其进行排序?我可以更改我的代码
  • 这段代码显示了经典的“物体恐惧症”。创建一个人(或任何有意义的名称)对象。并行数组不是很好的 OO。

标签: java list sorting arraylist collections


【解决方案1】:

可以按照以下步骤对多个相同大小的列表进行排序:

  1. 根据排序规则创建一个索引数组/列表(首先按名称,然后按生日,采用适当的 YYYYMMDD 格式等)
List<String> names  = Arrays.asList("bbb", "aaa", "bbb", "aaa");
List<String> phones = Arrays.asList("1023456", "1324560", "1227890", "1446752");
List<String> bdays  = Arrays.asList("20001122", "19980105", "20010614", "19990507");

int[] indexes = IntStream.range(0, names.size())
    .boxed()
    .sorted(Comparator.comparing(names::get).thenComparing(bdays::get))
    .mapToInt(Integer::intValue)
    .toArray(); // -> [1, 3, 0, 2]
  1. 根据索引对每个输入列表重新排序。 可以为此创建一个单独的方法:
private static List<String> sort(List<String> list, int[] indexes) {
    return Arrays.stream(indexes).mapToObj(list::get).collect(Collectors.toList());
}
// ...
System.out.println(sort(names,  indexes)); -> [aaa, aaa, bbb, bbb]
System.out.println(sort(phones, indexes)); -> [1324560, 1446752, 1023456, 1227890]
System.out.println(sort(bdays,  indexes)); -> [19980105, 19990507, 20001122, 20010614]

但是,创建一个容器对象来组合来自不同输入列表的值会更自然,这在 Java 16 中引入 record 类之后变得非常简单,并对这些对象进行排序:

record Person(String name, String phone, String bday) {}

List<Person> persons = IntStream.range(0, names.size())
    .boxed()
    .map(i -> new Person(names.get(i), phones.get(i), bdays.get(i)))
    .sorted(Comparator.comparing(Person::name).thenComparing(Person::bday))
    .collect(Collectors.toList());

persons.forEach(System.out::println);

输出:

Person[name=aaa, phone=1324560, bday=19980105]
Person[name=aaa, phone=1446752, bday=19990507]
Person[name=bbb, phone=1023456, bday=20001122]
Person[name=bbb, phone=1227890, bday=20010614]

【讨论】:

    最近更新 更多