java - 根据条件比较数组列表中的对象字段值,如果条件为真则删除

标签 java java-8 comparator

假设这些是 java bean 类 -

class Camp {
      int number;
      User userId;
      Date createDt;
 }

class User {
  private String id;
  private String name;
}

我想从 Camp 类型的 arrayList 中删除那些具有相同 userId 但较小 cre​​ateDt 的记录。

假设这是列表-

// ... the list is already populated
List<Camp> usersList = populatedListOfUser();

这就是方法 -

private List<Camp> skipByComparison(List<Camp> usersList){
    List<Camp> mainList = new ArrayList<Camp>();
    Set<Camp> s = new TreeSet<Camp>(new Comparator<Camp>() {

        @Override
        public int compare(Camp o1, Camp o2) {
            if(o1.getUserId().getId().equals(o2.getUserId().getId())) {
                if(o1.getCreatedTs().compareTo(o2.getCreatedTs()) < 0) {
                    usersList.remove(o1);
                    return -1;
                } else {
                    return 1;
                }
            } else {
                return 0;
            }
        }
    });
    s.addAll(usersList);
    mainList.addAll(s);
}

所以当我打电话时 -

usersList = skipByComparison(usersList);

我没有从 Camp 类型的 arrayList 中获取具有相同 userId 但较小 cre​​ateDt 的记录。

例如。如果我有 2 条具有相同 Camp.getUser().getId() 的记录,但 记录 1CreateDt 大于 记录 2 然后我想删除记录 2

最佳答案

您可以将代码更新为:

private List<Camp> skipByComparison(List<Camp> usersList){
    Set<Camp> s = new TreeSet<>((o1, o2) -> o1.getUserId().getId().equals(o2.getUserId().getId()) ? 
            o1.getCreateDt().compareTo(o2.getCreateDt()) : 0);
    s.addAll(usersList);
    return new ArrayList<>(s);
}

或者更好的是,您可以使用收集器和流来解决它:

private List<Camp> skipByComparisonStream(List<Camp> usersList) {
    return new ArrayList<>(usersList.stream()
            .collect(Collectors.toMap(c -> c.getUserId().getId(),
                    Function.identity(),
                    (a, b) -> a.getCreateDt().after(b.getCreateDt()) ? a : b))
            .values());
}

解释:对于两个日期可能相等的情况,您的Comparator当前不会返回任何值,您应该只是依赖于 Date 类的 compareTo 实现:

Set<Camp> s = new TreeSet<>(new Comparator<Camp>() {
    @Override
    public int compare(Camp o1, Camp o2) {
        return o1.getUserId().getId().equals(o2.getUserId().getId()) 
                ? o1.getCreateDt().compareTo(o2.getCreateDt()) : 0;
    }
});

完成此操作后,您可以使用 lambda 表达式将其简化为:

Set<Camp> s = new TreeSet<>((o1, o2) -> o1.getUserId().getId().equals(o2.getUserId().getId())
        ? o1.getCreateDt().compareTo(o2.getCreateDt()) : 0);

我所做的其余修改是简化执行顺序并清理冗余初始化。

旁白:我刚刚在另一个问题中得到纠正,并建议您改用 java.time.LocalDate对于 createDt 属性。

关于java - 根据条件比较数组列表中的对象字段值,如果条件为真则删除,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53637575/

相关文章:

Java 反射 : Call method from Interface name

jRuby 开发人员的 Java Swing 资源?

java - Java 8 中的可编辑 JComboBox 不会将 Enter 键转发到默认按钮

java - Optional#map 可以将输入参数的状态更改为 Function lambda 吗?

Java - 如何根据多个属性删除 ArrayList 中的重复项

java - 生成从 JSON 文件填充所有字段的 Java 代码

java - Swagger (Springfox) 仅查找 Controller @RequestBody (Spring Boot) 中使用的模型

java - jdk-9/jdk-8 和 jmh 中的新实例与新实例

Java-如何顺序查找数组中可能未填充的元素的最后一次出现?

通过 Comparator<T> 进行的 Java 排序将大部分时间花在 compare(Object,Object) 上