2013-12-13 114 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。