简体   繁体   English

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

[英]Sorting using collections for multiple parameter with null values

I wanted to sort list of records in my using multiple comparators. 我想使用多个比较器对记录列表进行排序。 It contains null values as well for some fields. 对于某些字段,它也包含空值。 I used java collections, to sort it, but it works only for one filed which is places at top. 我使用Java集合对它进行排序,但是它仅适用于放在顶部的一个文件。

My code: 我的代码:

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

I wanted to sort descending of LastLoginDate, LastActionDate. 我想对LastLoginDate,LastActionDate的降序进行排序。 Either or both fields might be null in some cases. 在某些情况下,这两个字段中的一个或两个都可能为null。 And ascending of names. 和名字升序。 And to display all other null field values(LastLoginDate, LastActionDate) at last. 最后显示所有其他空字段值(LastLoginDate,LastActionDate)。 But when i sort, with this code it takes only the first defined method to sort. 但是,当我排序时,使用此代码仅需要对第一个定义的方法进行排序。 Example, if i have 3 records having same, "LastLoginDate" then it should check sort with "LastActionDate" values. 例如,如果我有3条记录具有相同的“ LastLoginDate”,则应检查“ LastActionDate”值的排序。 But its not sorted with this logic. 但是它不符合这种逻辑。

So i added another algorithm to sort, since some fields has null values it is not properly sorted. 因此,我添加了另一种算法进行排序,因为某些字段具有空值,因此无法正确排序。

My second logic: 我的第二个逻辑:

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

Here i am getting the integer values to compare it "compareLastActionDate, compareLastName, compareLastLoginDate". 在这里,我正在获取整数值以进行比较“ compareLastActionDate,compareLastName,compareLastLoginDate”。

I would recommend you to use the java8 comparators, it provides some helpful methods to compare based in multiple attributes with thenComparing() . 我建议您使用java8比较器,它提供了一些有用的方法,可以使用thenComparing()进行基于多个属性的比较。

If you don't want to / can't use, try two wrap part of that repetitive code in one or multiple custom Comparator or in a helper method. 如果您不想/不能使用,请在一个或多个自定义Comparator或辅助方法中尝试将重复代码的两个部分包装起来。

Here, for simplicity , the following helper method is used ( in java8 you can use method references ): 在这里, 为简单起见 ,使用了以下辅助方法( 在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);
}

In your method, you could use this nullSort() method, to check first for lastLoginDate descending and nulls last (false, false) , then lastActionDate again descending and nulls last. 在您的方法中,您可以使用此nullSort()方法,先检查lastLoginDate降序,最后检查null (false, false) ,然后再检查lastActionDate降序,最后检查null。

A difference with your comparator is that you stop evaluating here when both are null. 与比较器的不同之处在于,当两者均为空时,您将在此处停止评估。 It would be better that when lastLoginDate and lastActionDate are nulls you keep ordering by lastName and firstName . lastLoginDatelastActionDate为null时, lastLoginDatelastNamefirstName排序。 If you don't want this, you can add if (result == 0) return 0; 如果您不希望这样做,则可以添加if (result == 0) return 0; after the second if in the method below. if在下面的方法中第二个之后。

Then after the dates are compared, you compare lastName and then firstName both ascending and nulls last (true, false) . 然后在比较日期之后,比较lastNamefirstName ,然后比较last和last (true, false) null。

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

I used simple date format to filter the list. 我使用简单的日期格式来过滤列表。 Here is my working code, 这是我的工作代码,

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM