2014-05-20 4 views
0

Я использую Java компаратор для сортировки одного моего объекта, основываясь на некотором значении в этом объекте, как показано ниже:Java компаратор сортировки

@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 sort, как мне получить события с наивысшими рангами, а затем нижние разряды, а затем с нулевым значением для рангов в конце?

+3

Сортировка только в одном порядке (скажем, ASCENDING), а затем вызов Collections.reverse() изменит его на убывающий порядок. Не заново изобретайте колесо :) – TheLostMind

+3

Могу ли я предложить вам использовать Guava для создания своего «компаратора»? Его заказывающие объекты довольно приятные. https://code.google.com/p/guava-libraries/wiki/OrderingExplained. Он включает в себя отличные методы «nullsFirst» и «nullsLast». –

+1

@WhoAmI - это именно то, что OP сказал, что они НЕ хотят. –

ответ

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

Это будет работать, за исключением того, что цифры в первых двух условиях IF должны быть заменены. Благодарю. –

1

ли нулевые чеки внутри compare, перед логикой, которая проверяет sortOrder. Затем позвоните только compareTo, как только вы узнаете, что оба объекта не являются null.

1

Судя по сопоставлениям, которые вы делаете на них, я предположил, что поля rank и id являются объектами Integer. Если это так, вы можете выполнить нулевые проверки в отдельном компараторе и использовать его для упорядочения объектов на основе элементов внутри объекта.

Я немного упростил ваш сценарий, только работая с классом Tag с элементами и id.

Так отведенный нулевая проверка компаратор будет выглядеть следующим образом: (Я включил аспект заказа здесь тоже.)

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 & I = 2, R = 3 & I = 7, R = 6 & I = 3, R = 6 & I = 5, R = null & I = 1, R = null & I = 2, R = NULL & I = 4, R = NULL & I = 6] DESCENDING [R = 6 & I = 5, R = 6 & I = 3, R = 3 & I = 7, R = 1 & I = 2, R = NULL & I = 6, R = NULL & I = 4, R = NULL & I = 2, R = NULL & = 1]

+0

Мне нравится этот подход, но я также хочу иметь дело с событиями, в которых ранги имеют одинаковые значения (нулевые или одинаковые значения). Причина, по которой я хочу иметь дело, заключается в том, что я делаю разбивку на страницы после применения сортировки, и база данных не гарантирует порядок возвращаемых событий каждый раз. Поэтому, когда я нахожу равные значения, я сортирую события на основе их идентификатора. –

+0

Правосудие, это выполнимо, я отредактировал свой ответ совсем немного. Читая дублированный вопрос, помеченный для этого вопроса и применяя его к вашему сценарию, я использовал сверкающий сверкающий компаратор и добавил его в возможности упорядочения, затем использовал его в компараторе для класса Tag и включил как ранг, так и поля id внутри этого. Вы увидите на выходе, что равные ранги упорядочены по Id в том же порядке, но вы всегда можете изменить порядок, если хотите. Я также предположил, что id является Integer, но он будет одинаково хорошо работать с любым объектом, который реализует Comparable. –

Смежные вопросы