使用集合对具有空值的多个参数进行排序

Sorting using collections for multiple parameter with null values

我想使用多个比较器对记录列表进行排序。 它也包含某些字段的空值。 我使用 java 集合对其进行排序,但它仅适用于位于顶部的一个字段。

我的代码:

Collections.sort(userListResult, new Comparator<UserDto>()
{
    @Override
    public int compare(UserDto userDto1, UserDto userDto2)
    {          

        if (userDto1.getLastLoginDate() != null && userDto2.getLastLoginDate() != null && userDto2.getLastLoginDate().compareTo(userDto1.getLastLoginDate()) != 0) {
            return userDto2.getLastLoginDate().compareTo(userDto1.getLastLoginDate());
        }
        if (userDto1.getLastLoginDate() != null && userDto2.getLastLoginDate() == null) {
            return -1;
        }
        if (userDto1.getLastLoginDate() == null && userDto2.getLastLoginDate() != null) {
            return 1;
        }

        if (userDto1.getLastActionDate() != null && userDto2.getLastActionDate() != null && userDto2.getLastActionDate().compareTo(userDto1.getLastActionDate()) != 0) {
            return userDto2.getLastActionDate().compareTo(userDto1.getLastActionDate());
        }
        if (userDto1.getLastActionDate() == null && userDto2.getLastActionDate() == null) {
            return 0;
        }
        if (userDto1.getLastActionDate() == null && userDto2.getLastActionDate() != null) {
            return 1;
        }
        if (userDto1.getLastActionDate() != null && userDto2.getLastActionDate() == null) {
            return -1;
        }

        if (userDto1.getLastName() != null && userDto2.getLastName() != null && userDto1.getLastName().compareTo(userDto2.getLastName()) != 0) {
            return userDto1.getLastName().compareTo(userDto2.getLastName());
        }
        if (userDto1.getLastName() != null && userDto2.getLastName() == null) {
            return -1;
        }
        if (userDto1.getLastName() == null && userDto2.getLastName() != null) {
            return 1;
        }
        if (userDto1.getFirstName().compareTo(userDto2.getFirstName()) != 0) {
            return userDto1.getFirstName().compareTo(userDto2.getFirstName());
        }
        if (userDto1.getFirstName() != null && userDto2.getFirstName() == null) {
            return -1;
        }
        if (userDto1.getFirstName() == null && userDto2.getFirstName() != null) {
            return 1;
        }
        return 0;
    }
});*/

我想对 LastLoginDate、LastActionDate 进行降序排序。在某些情况下,一个或两个字段可能为空。 和升序的名字。最后显示所有其他空字段值(LastLoginDate、LastActionDate)。 但是当我排序时,使用这段代码它只需要第一个定义的方法来排序。 例如,如果我有 3 条具有相同 "LastLoginDate" 的记录,那么它应该检查 "LastActionDate" 值的排序。但是它不是按照这个逻辑排序的。

所以我添加了另一种算法来排序,因为某些字段具有空值,所以排序不正确。

我的第二个逻辑:

if (userDto1.getLastLoginDate() != null && userDto2.getLastLoginDate() != null && userDto2.getLastLoginDate().compareTo(userDto1.getLastLoginDate()) != 0) {
        compareLastLoginDate = userDto2.getLastLoginDate().compareTo(userDto1.getLastLoginDate()); 
    }
         if (userDto1.getLastActionDate() != null && userDto2.getLastActionDate() != null && userDto2.getLastActionDate().compareTo(userDto1.getLastActionDate()) != 0) {
                compareLastActionDate = userDto2.getLastActionDate().compareTo(userDto1.getLastActionDate());
            }
         if (userDto1.getLastName() != null && userDto2.getLastName() != null && userDto1.getLastName().compareTo(userDto2.getLastName()) != 0) {
                compareLastName = userDto1.getLastName().compareTo(userDto2.getLastName());
            }
         if (compareLastLoginDate == 0) {
             return ((compareLastActionDate == 0) ? compareLastName : compareLastActionDate);
         }
         else {
             return compareLastLoginDate;
         }

我在这里获取整数值来比较它 "compareLastActionDate, compareLastName, compareLastLoginDate"。

我建议您使用 java8 比较器,它提供了一些有用的方法来基于多个属性与 thenComparing() 进行比较。

如果您不想/不能使用,请尝试在一个或多个自定义 Comparator 或辅助方法中两次包装重复代码的一部分。

这里,为简单起见[​​=41=],使用了以下辅助方法(在java8中你可以使用方法引用):

public static <R extends Comparable<? super R>> int nullSort(R r1, R r2,
                                                             boolean ascending,
                                                             boolean nullsFirst) {
    R rs1 = ascending ? r1 : r2, rs2 = ascending ? r2 : r1;
    if (rs1 != null && rs2 != null) return rs1.compareTo(rs2);
    else if (r1 == null && r2 == null) return 0;
    else if (r1 == null) return (nullsFirst ? -1 : 1);
    else return (nullsFirst ? 1 : -1);
}

在您的方法中,您可以使用此 nullSort() 方法,首先检查 lastLoginDate 降序和最后的空值 (false, false),然后再次检查 lastActionDate 降序和最后的空值.

与比较器的不同之处在于,当两者都为空时,您将在此处停止计算。当 lastLoginDatelastActionDate 为 null 时,您继续按 lastNamefirstName 排序会更好。如果你不想这样,你可以在下面的方法中的第二个 if 之后添加 if (result == 0) return 0;

然后在比较日期之后,比较 lastName 然后 firstName 升序和空值最后 (true, false).

@Override
public int compare(UserDto dto1, UserDto dto2) {
    int result;
    if ((result = nullSort(dto1.getLastLoginDate(), dto2.getLastLoginDate(), 
            false, false)) != 0) return result;
    if ((result = nullSort(dto1.getLastActionDate(), dto2.getLastActionDate(), 
            false, false)) != 0) return result;
    if ((result = nullSort(dto1.getLastName(), dto2.getLastName(), 
            true, false)) != 0) return result;
    if ((result = nullSort(dto1.getFirstName(), dto2.getFirstName(), 
            true, false)) != 0) return result;
    return 0;
}

我使用简单的日期格式来过滤列表。 这是我的工作代码,

public int compare(UserDto userDto1, UserDto userDto2) {
    DateFormat format = new SimpleDateFormat("yyyy-MM-dd");

    if (userDto1.getLastLoginDate() != null && userDto2.getLastLoginDate() != null && userDto2.getLastLoginDate().compareTo(userDto1.getLastLoginDate()) != 0) {
        String Date1 = format.format(userDto1.getLastLoginDate());
        String Date2 = format.format(userDto2.getLastLoginDate());
        if (Date1.equals(Date2)) {
            if (userDto1.getLastActionDate() != null && userDto2.getLastActionDate() != null && userDto2.getLastActionDate().compareTo(userDto1.getLastActionDate()) != 0) {
                String Date3 = format.format(userDto1.getLastActionDate());
                String Date4 = format.format(userDto2.getLastActionDate());
                if (Date3.equals(Date4)) {
                    if (userDto1.getLastName() != null && userDto2.getLastName() != null && userDto1.getLastName().compareTo(userDto2.getLastName()) != 0) {
                        return userDto1.getLastName().compareTo(userDto2.getLastName());
                    }
                } else {
                    return userDto2.getLastActionDate().compareTo(userDto1.getLastActionDate());
                }
            }
        } else {
            return userDto2.getLastLoginDate().compareTo(userDto1.getLastLoginDate());
        }

    }
    if (userDto1.getLastLoginDate() != null && userDto2.getLastLoginDate() == null) {
        return -1;
    }
    if (userDto1.getLastLoginDate() == null && userDto2.getLastLoginDate() != null) {
        return 1;
    }
    if (userDto1.getLastLoginDate() == null && userDto2.getLastLoginDate() == null) {
        return userDto1.getLastName().compareTo(userDto2.getLastName());
    } }