Java Comparator排序顺序

时间:2014-05-20 07:07:28

标签: java sorting comparator comparable

我正在使用Java Comparator根据该对象中的某个值对我的一个对象进行排序,如下所示:

@Override
public int compare(Event e1, Event e2) {
   if(sortOrder.equalsIgnoreCase(DESCENDING))
       return compareTo(e2, e1);
   else
       return compareTo(e1, e2);
}

public int compareTo(Event e1, Event e2) {
     Tag t1 = getTag(e1, tagName, tagType); 
     Tag t2 = getTag(e2, tagName, tagType);

     if(t1!=null && t2!=null){
        if(t1.getRank()==null && t2.getRank()!=null)
            return 1;
        else if(t2.getRank()==null && t1.getRank()!=null)
            return -1;          
        else if (t1.getRank() < t2.getRank())
            return -1;
        else if (t1.getRank() > t2.getRank())
            return 1;
        else
            return e1.getId().compareTo(e2.getId()); //If rank null or equal compute rank based on id.
     }
     return 0;
}

Tag getTag(Event e, String tagName, TagTypeEnum tagType){
    List<Tag> tags = e.getTags();
    for(CTagsDO tag: tags){
        if((tag.getType().getId() == tagType.getId()) && (tag.getName().equals(tagName)))
            return tag;
    }
    return null;
} 

这里我比较2个具有一些等级值的事件中的2个标签。我根据标签对象中的这个等级对事件进行排序。

ASCENDING命令可以很好地放置具有最低等级值的事件,然后是具有较高等级的事件,并将所有具有等级值的事件放在最后。

但是对于DESCENDING命令,因为我只是执行一个反向的ASCENDING命令,它将所有具有空值的事件放在顶部,然后从排名最高的事件开始并移动到最低等级。

在DESCENDING排序中,如何获得排名最高的事件,然后是排名较低的事件,然后是排名最后的排名?

3 个答案:

答案 0 :(得分:1)

您需要在sortOrder.equalsIgnoreCase(DESCENDING)中使用compareTo

@Override
public int compare(Event e1, Event e2) {
   if(sortOrder.equalsIgnoreCase(DESCENDING))
       return compareTo(e2, e1);
   else
       return compareTo(e1, e2);
}

public int compareTo(Event e1, Event e2) {
     Tag t1 = getTag(e1, tagName, tagType); 
     Tag t2 = getTag(e2, tagName, tagType);

     if(t1!=null && t2!=null){
        if(t1.getRank()==null && t2.getRank()!=null)
            return sortOrder.equalsIgnoreCase(DESCENDING) ? 1 : -1;
        else if(t2.getRank()==null && t1.getRank()!=null)
            return sortOrder.equalsIgnoreCase(DESCENDING) ? -1 : 1;          
        else if (t1.getRank() < t2.getRank())
            return -1;
        else if (t1.getRank() > t2.getRank())
            return 1;
        else
            return e1.getId().compareTo(e2.getId()); //If rank null or equal compute rank based on id.
     }
     return 0;
}

答案 1 :(得分:1)

在检查compare的逻辑之前,在sortOrder内进行空检查。然后,只有在您知道两个对象都不是compareTo时才会调用null

答案 2 :(得分:1)

根据您对它们进行的比较判断,我认为rankid字段是Integer个对象。如果是这种情况,您可以在单独的比较器中执行空检查,并使用它来根据对象内的元素对对象进行排序。

我只使用Tag类与rankid元素合作,略微简化了您的方案。

所以抽象的空检查比较器看起来像这样:(我在这里也包括了排序方面。)

public class NullsLastOrderedComparator<T extends Comparable<T>> implements Comparator<T>{

    public static final String ASCENDING = "ASCENDING";
    public static final String DESCENDING = "DESCENDING";

    private String sortOrder;

    public NullsLastOrderedComparator() {
        this(ASCENDING);
    }

    public NullsLastOrderedComparator(final String sortOrder) {
        this.sortOrder = sortOrder;
    }

    public int compare(final T o1, final T o2) {
        if( o1 == null && o2 == null) {
            return 0;
        }

        if( o1 == null ) {
            return 1;
        }

        if( o2 == null ) {
            return -1;
        }

        if(this.sortOrder.equalsIgnoreCase(DESCENDING)) {
            return o2.compareTo(o1);
        }

        return o1.compareTo(o2);
    }
}

然后可以在要比较的类的比较器中使用它。您可以通过检查初始结果为0并在该点按第二个元素排序来包括要排序的两个元素。这是一个示例TagComparator类:

public class TagComparator implements Comparator<Tag>{

    public static final String ASCENDING = "ASCENDING";
    public static final String DESCENDING = "DESCENDING";

    private String sortOrder;

    public TagComparator() {
        this(ASCENDING);
    }

    public TagComparator(final String sortOrder) {
        this.sortOrder = sortOrder;
    }

    public int compare(final Tag o1, final Tag o2) {
        final Comparator<Integer> comparator = new NullsLastOrderedComparator<Integer>(this.sortOrder);
        final int rankCompare = comparator.compare( o1.getRank(), o2.getRank() );

        if( rankCompare == 0 ) {
            return comparator.compare( o1.getId(), o2.getId() );
        }

        return compare;
    }
}

然后我的标签类看起来像这样:

public class Tag {

    private Integer rank;
    private Integer id;

    public Tag(final Integer rank, final Integer id) {
        this.rank = rank;
        this.id = id;
    }

    public Integer getRank() {
        return this.rank;
    }

    public void setRank(final Integer rank) {
        this.rank = rank;
    }

    public Integer getId() {
        return this.id;
    }

    public void setId(final Integer id) {
        this.id = id;
    }

    @Override
    public String toString() {
        return "R=" + this.rank + "&I=" + this.id; //Tag: " + super.toString() + "
    }

    public static void main(final String[] args) {
        final List<Tag> tags = new ArrayList<Tag>();
        tags.add(new Tag(null, 1));
        tags.add(new Tag(1, 2));
        tags.add(new Tag(null, 2));
        tags.add(new Tag(6, 5));
        tags.add(new Tag(null, 4));
        tags.add(new Tag(6, 3));
        tags.add(new Tag(null, 3));
        tags.add(new Tag(3, 7));

        System.out.println("ASCENDING");
        Collections.sort(tags, new TagComparator(TagComparator.ASCENDING));
        System.out.println(tags);

        System.out.println("DESCENDING");
        Collections.sort(tags, new TagComparator(TagComparator.DESCENDING));
        System.out.println(tags);
    }
}

输出是这样的:

  

ASCENDING   [R = 1&amp; I = 2,R = 3&amp; I = 7,R = 6&amp; I = 3,R = 6&amp; I = 5,R = null&amp; I = 1,R = null&amp; I = 2,R = null&amp; I = 4,R = null&amp; I = 6]   DESCENDING   [R = 6&amp; I = 5,R = 6&amp; I = 3,R = 3&amp; I = 7,R = 1&amp; I = 2,R = null&amp; I = 6,R = null&amp; I = 4,R = null&amp; I = 2,R = null&amp; I = 1]