2013-12-13 117 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的实例。

为了获得当前的StatusIterable<String>被转换为SortedSet<Status>。枚举默认按照声明顺序排序,因此需要完成的所有操作都是调用transformed.last()来查找“最高”状态。

我认为这种方法比更好,因为它将Status和相关的方法封装到一个类中。

我建议您在代码的其他地方使用Status对象而不是String,因为这样会增加类型安全性。

+0

如果您可以处理具有“集合”而不是“Iterable”的输入到'getStatus',您可以使用'TreeSet'的构造函数而不是编写自己的循环。 –

+0

@DavidWallace需要在任何情况下进行转换。我想我可以使用自定义的比较器来实现转换,但我认为这会击败对象并且还需要更多的查找。 –

+0

+1仅用于在整个代码中使用'Status'而不是'String'。 –

2

我会建议使用一个枚举的状态值而不是一个字符串。
然后,您可以简单地使用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; 

这样你扫描列表仅一次。 如果所有状态都可用,则最终状态为可用。 如果至少有一个元素是Partial,并且没有NotAvailable,那么您的最终状态是Partial。 如果只有一个NotAvailable状态,则您的最终状态为NotAvailable。