2014-12-21 6 views
2

предположив, что у меня есть список испытаний, как показано ниже:Как отсортировать список объектов

public class Test { 
    public static enum Unit { 
     DAY, WEEK, MONTH, YEAR /* , DAY_TO_DAY */ 
    } 

    private int value; 
    private Unit unit; 
    public int getValue() { 
     return value; 
    } 
    public void setValue(int value) { 
     this.value = value; 
    } 
    public Unit getUnit() { 
     return unit; 
    } 
    public void setUnit(Unit unit) { 
     this.unit = unit; 
    } 
} 

у меня будет список испытаний с ниже значений:

3 дня, 5 месяц , 5 дня, 6 года, 6 недели, 12 недели,

и наш результат expection, как показано ниже:

3 день, 5 дня, 6 недели, 12 недели, 5 месяца, 6 года

В настоящее время я создать код, как показано ниже

Collections.sort(tests, new Comparator<Test >() { 
    @Override 
    public int compare(Test o1, Test o2) { 
    if(o1.getValue() > o2.getValue()) return 1; 
    if(o1.getValue() < o2.getValue()) return -1; 
    return 0; 
    } 

Однако, это только сортировку по значению, а не группа. Результат с вышеуказанной реализацией:

3 день, 5 день, 5 месяц, 6 неделя, 6 год, 12 неделя.

В этом случае сообщите мне, как можно удовлетворить два условия (единица измерения и значения). Спасибо.

+5

Сравните устройство во-первых, если сравнение возвращает 0, сравните значение. –

+1

Это неправильное решение. 35 дней больше одного месяца. – Behnil

+0

Вы используете Java 8? Если нет, вы используете threetenbp? Если нет, вы используете Joda TIme? – fge

ответ

5

Вам необходимо преобразовать первый в общий формат, а затем сравнить. Поскольку дни - это ваш наименьший тип, вы должны преобразовать два экземпляра, которые вы сравниваете, в течение нескольких дней, а затем сравните их на основе этого.

Но у вас есть некоторые значения, которые нужно сделать в первую очередь. Как долго длится месяц? Это более 30 дней, или короче, или то же самое?

0

Если вы действительно хотите сделать это таким образом, назначить Перечисления значения таким образом: ДЕНЬ (1), неделя (7), МЕСЯЦ (31), YEAR (365)

чем размножаются в вашем comperator Unit.getValue() * значение

eg 4 МЕСЯЦА дает вам 31 * 4 = 124 больше, чем 100 дней.

все еще у вас есть проблема, что тегер месяцев с менее чем 31 дней. рекомендуется преобразовать в некоторые общие единицы даты, например. юда время.

1

Если вы просто хотите, чтобы сравнить по вашему примеру следующий код решает эту проблему:

Collections.sort(terms, new Comparator<Test>() { 
    @Override 
    public int compare(final Test o1, final Test o2) { 
     int unitCompare = o1.getUnit().compareTo(o2.getUnit()); 
     if (unitCompare == 0) { 
      return o1.getValue() - o2.getValue(); 
     } 
     return unitCompare; 
    } 
}); 

Однако этот код НЕ фактор в том, что месяцы может иметь различную длину и делает код НЕ Фактор в том, что 35 дней больше, чем месяц.

Для того, чтобы сделать это я предлагаю, что классы от java.time пакета (например, java.time.Period) используются, чтобы сделать правильные сравнения (хороший след, чтобы узнать об этом можно найти here). Если Java 8 не является опцией, то Joda Time обеспечивает тот же тип функциональности.

0

Пожалуйста, используйте функцию CompareTo, как показано ниже:

public int compareTo(Object o) { 
     Test t1 = (Test)this; 
     Test t2 = (Test)o; 
     if(t1.getValue()*(t1.getUnit().getValue()+1) > t2.getValue()*(t2.getUnit().getValue()+1)) return 1; 
     if(t1.getValue()*(t1.getUnit().getValue()+1) < t2.getValue()*(t2.getUnit().getValue()+1)) return -1; 
     return 0; 
    } 

и изменить перечисление на

public static enum Unit { 
    DAY(1), WEEK(7), MONTH(31), YEAR(365) ;/* , DAY_TO_DAY */ 
     private final int id; 
     Unit(int id) { this.id = id; } 
    public int getValue() { return id; } 
    } 

Теперь вы используете collection.sort(), и он будет отсортирован автоматически

+0

SImply, длина значения равна динамичный, может быть, 45 дней или 30 дней или 23 месяца ... Спасибо за вашу поддержку – user3737020

1

Используйте TimeUnit, чтобы заменить ваш Unit перечисление. Поэтому

Ваш Term класс может иметь .toMillis() метод, который очень прост:

public final long toMillis() 
{ 
    return timeUnit.toMillis(value); 
} 

Вы можете просто Long.compare(o1.toMillis(), o2.toMillis()) в вашем Comparator.

Другие решения:

  • если вы используете Java 8, используют новую дату/время API;
  • Если вы используете Java 7- и threetenbp, используйте те же методы, backported;
  • Если вы используете Java 7- и Joda Time, используйте Period. Это почти эквивалентно таковому для Java 8/threetenbp.
Смежные вопросы