根据条件比较数组列表中的对象字段值,并在条件为真时删除

时间:2018-12-05 17:19:13

标签: 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但createDt较小的记录。

假设这是列表-

// ... 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但较小的createDt。

例如如果我有2条记录具有相同的Camp.getUser().getId(),但是record 1的{​​{1}}大于CreateDt,那么我要删除record 2

2 个答案:

答案 0 :(得分: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);
}

或者更好的是,您可以使用Collectors和流将其解决为:

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的情况,您的equal当前没有返回任何值,您可能应该仅依靠{{1 }}为此的compareTo类的实现:

Date

执行此操作后,可以使用lambda表达式将其简化为:

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

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

放在一边:我刚刚在另一个问题中得到了改正,因此也建议您改为对Set<Camp> s = new TreeSet<>((o1, o2) -> o1.getUserId().getId().equals(o2.getUserId().getId()) ? o1.getCreateDt().compareTo(o2.getCreateDt()) : 0); 属性使用java.time.LocalDate

答案 1 :(得分:2)

您可以使用toMap收集器:

Collection<Camp> values = usersList.stream()
                .collect(toMap(c -> c.getUser().getId(),
                        Function.identity(),
                        BinaryOperator.maxBy(Comparator.comparing(Camp::getCreateDt))))
                .values();

see this答案以解释有关toMap的工作原理