【问题标题】:Sort a List by a date present in another list按另一个列表中存在的日期对列表进行排序
【发布时间】:2021-08-06 12:17:42
【问题描述】:

我有这样的情况:

@Getter
@Setter
public class ObjectA {
      private Integer id;
      private String code;
      private String name;
}

@Getter
@Setter
public class ObjectB {
      private Integer id;
      private Timestamp createdOn;
}

我必须对还包含 List<ObjectB> 的 ID 的 List<ObjectA> 进行排序,并且排序必须是:

  • List<ObjectA> 中包含的 List<ObjectB> 的“createdOn”属性的降序日期,可与 ID 区分开来
  • 按降序命名
  • 降序代码

我使用 .sort() 和比较器按名称和代码排序:

 listA.sort(o -> o.getName())
                .thenComparing(o -> o.getCode()).reversed();

我无法生成的部分是基于一个属性对列表进行排序,该属性不存在于正在排序的列表中,但另一个可通过 id 区分。

感谢大家的帮助。

【问题讨论】:

  • 你需要通过它们的 id 将 A 元素映射到它们的 B 对应元素。出于性能原因,我建议为 B 构建一个映射,然后在比较器中映射,例如Comparator.comparing(a -> mapOfB.get(a.getId()).getCreatedOn())。当然,您必须处理不存在的映射(即get() 返回 null)等。
  • 并非 List 的所有内容都存在于 List - 它会转到 NullPointer
  • 没错,这就是我在上一句中所指的内容。不要指望 SO 上的生产就绪解决方案。您通常会获得大纲或简化代码来帮助您入门,但您仍需要在代码中投入一些精力。

标签: java sorting comparable


【解决方案1】:

我建议您将 ObjectB 的列表转换为 Map<id, createdOn>,因为按键检索元素在 Map 中是 O(1) 而在 List 中是 O(n)。

Map<Integer, Timestamp> createdOnMap =
    bList.stream().collect(Collectors.toMap(ObjectB::getId, ObjectB::getCreatedOn));

然后通过获取此映射的值进行比较,如果它不存在,则通过将该值与最大/最小值进行比较来决定将其放在列表中的第一个还是最后一个。 LocalDateTime 的示例:

aList.stream()
        .sorted(Comparator.comparing(objectA -> createdOnMap.getOrDefault(objectA.getId(), LocalDateTime.MAX)))
        .collect(Collectors.toList())

在 createdOnMap 没有此 id 的值的情况下,它与 LocalDateTime.MAX/MIN 进行比较。

如果您还希望在最终列表中包含 List 中不存在但存在于 List 中的元素,那么您需要在通过将 ObjectB 转换为 ObjectA 进行排序之前自行添加这些元素。

【讨论】:

    【解决方案2】:

    也许你需要这样的东西:

    Map<Integer, Timestamp> mapOfB = listB.stream()
                                          .collect(Collectors.toMap(ObjectB::getId,
                                                                    ObjectB::getCreatedOn));
    
    listA.sort(Comparator.comparing(o-> mapOfB.get(((ObjectA)o).getId()),
                                    Comparator.nullsLast(Comparator.reverseOrder()))
                         .thenComparing(o->((ObjectA)o).getName())
                         .thenComparing(o->((ObjectA)o).getCode(), Comparator.reverseOrder()));
    

    【讨论】:

    • @Thomas 谢谢你,我同意你的观点,解决方案太昂贵了。 Yayotron 的解决方案非常好。
    • @Thomas 我改变了答案
    猜你喜欢
    • 1970-01-01
    • 2021-01-23
    • 2020-03-08
    • 2018-04-02
    • 2014-05-28
    • 2012-02-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多