2013-12-13 2 views
0

У меня есть переменная, которая может принимать три возможных значения (или статус): Available, Partial, Not Available.Пользовательское сравнение с использованием компаратора

Теперь у меня есть список этих статусов. Моя задача состоит в том, чтобы суммировать весь результат на один статус. Я имею в виду, что даже если один из статусов в списке Not Available, тогда общее состояние становится Not Available.

Если все статусы в списке: Available, а один - Partial, тогда общее состояние Partial.

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

public class StringsInCusomOrder { 

public static String overallStatus(ArrayList<String> statusList) throws Exception 
{ 
    HashMap<String, Integer> map = new HashMap<String, Integer>(); 
    map.put("Available", 0); 
    map.put("Partial", 1); 
    map.put("Not Available", 2); 

    String overallstatus = "Available"; 
    int value = 0; 

    for(String s : statusList) 
    { 
     if(map.get(s) > value) 
     { 
      overallstatus = s; 
      value = map.get(s);    
     } 
    } 
    return overallstatus; 

} 
public static void main(String[] args) throws Exception { 

    ArrayList<String> statusList = new ArrayList<String>(); 
    statusList.add("Available"); 
    statusList.add("Partial"); 
    statusList.add("Not Available"); 
    statusList.add("Partial"); 

    System.out.println(overallStatus(statusList)); 
} 
} 

Я задавался вопросом, есть ли лучший способ сделать это? Могу ли я использовать компаратор для выполнения этого пользовательского сравнения?

+1

Не можете ли вы просто использовать метод 'contains'? –

+0

Поскольку ваш код работает, вы можете опубликовать его по адресу http://codereview.stackexchange.com/, если хотите обсудить лучший способ сделать это. –

+0

Вы также можете использовать 'enum' вместо' String'. –

ответ

2

Если вы хотите использовать contains операцию, то стоит отметить, что это O(n) для List, но только O(1) для Set так уборщик подход был бы:

public String getStatus(final Collection<String> in) { 
    final Set<String> set = new HashSet<>(in); 
    if (set.contains("Not Available")) { 
     return "Not Available"; 
    } 
    if (set.contains("Partial")) { 
     return "Partial"; 
    } 
    return "Available"; 
} 

Я предпочитаю, чтобы мой подход, основанный enum однако, как это быстрый путь к тирании if с.

1
public String listStatus(List<String> toCheck) { 

    if (toCheck.contains("Not available")) { 
     return "Not available"; 
    } else if (toCheck.contains("Partial")) { 
     return "Partial"; 
    } else { 
     return "Available"; 
    } 
} 
+1

Поскольку вы в большинстве случаев спрашиваете ... –

+0

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

1

Попробуйте один

public static String overallStatus(ArrayList<String> statusList) 
    { 
     if(statusList.contains("Not Available")) 
      return "Not Available"; 
     else if(statusList.contains("Partial")) 
       return "Not Available"; 
     return "Available"; 
    } 
1

Я хотел бы использовать enum класс:

public enum Status { 

    AVAILABLE("Available"), 
    PARTIAL("Partial"), 
    NOT_AVAILABLE("Not Available"); 
    private static final Map<String, Status> LOOKUP; 

    static { 
     LOOKUP = new HashMap<>(); 
     for (final Status s : values()) { 
      LOOKUP.put(s.key, s); 
     } 
    } 

    public static Status lookup(final String status) { 
     final Status s = LOOKUP.get(status); 
     if (status == null) { 
      throw new IllegalArgumentException(status + " not a vaild status."); 
     } 
     return s; 
    } 

    public static Status getStatus(final Iterable<String> input) { 
     final SortedSet<Status> transformed = new TreeSet<>(); 
     for (final String in : input) { 
      transformed.add(lookup(in)); 
     } 
     return transformed.last(); 
    } 

    //Alternative method not using a SortedSet and getting the max on the fly 
    public static Status getStatus(final Iterable<String> input) { 
     Status max = Status.AVAILABLE; 
     for (final String in : input) { 
      final Status curr = lookup(in); 
      if (curr.compareTo(max) > 0) { 
       max = curr; 
      } 
     } 
     return max; 
    } 

    private final String key; 

    private Status(String key) { 
     this.key = key; 
    } 
} 

enum инкапсулирует коды статуса. Существуют методы static, чтобы превратить ваш статус String в экземпляр enum.

Для того, чтобы получить текущий Status, Iterable<String> превращается в SortedSet<Status>. Перечисления по умолчанию сортируются в порядке декларации, поэтому все, что нужно сделать, это вызов transformed.last(), чтобы найти «самый высокий» статус.

Я думаю, что этот подход лучше сравнивать String, поскольку он инкапсулирует ваш Status и связанные с ним методы в класс.

Я бы порекомендовал вам использовать объект Status, а не String в другом месте вашего кода, так как это добавляет безопасность типов.

+0

Если вы можете обрабатывать 'Collection', а не' Iterable' для ввода 'getStatus', вы можете просто использовать конструктор для TreeSet вместо написания собственного цикла. –

+0

@DavidWallace необходимо сделать преобразование в любом случае. Я полагаю, что я мог бы использовать пользовательский компаратор, который сделал преобразование «на лету», но я думаю, что это победит объект, а также потребует гораздо больше поисков. –

+0

+1 только для использования 'Status' вместо' String' всего кода. –

2

Я бы предложил использовать Enum для значений статуса вместо String.
Вы можете просто использовать Collections.min(), чтобы получить самую низкую стоимость вашего EnumSet так:

public Enum Status { 
    NOT_AVAILABLE, 
    PARTIAL, 
    AVAILABLE 
} 

public Status overallStatus(EnumSet<Status> statusList) { 
    return Collections.min(statusList); 
} 
+0

+1. Это фантастика. Кроме того, это просто называется 'min'. –

+0

Давид прав, обновил пример. – Kai

0

Вы можете использовать лучший подход:

String currentStatus = statusList.get(0); 
for(String s : statusList) { 
    if (s.equalsIgnoreCase("Partial")) 
     currentStatus = s; 
    else if (s.equalsIgnoreCase("NotAvailable"); 
     return s; 
} 
return currentStatus; 

Таким образом, вы просканировать список только один раз. Если доступны все состояния, вы можете указать конечное состояние. Если хотя бы один из элементов является частичным и нет NotAvailable, ваше конечное состояние является частичным. Если есть только одно состояние NotAvailable, ваше конечное состояние NotAvailable.

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