2017-03-03 61 views
0

我有一個名爲Task我不能觸摸,因爲它是一個傳統的代碼,我有兩個ArrayListTask類,我需要比較的類。項目可以以任何順序存在,也可以在ArrayList中有重複項目。比較兩個ArrayList中的兩種比較?

什麼是最好的方法來比較兩個ArrayList其中的對象,並打印出缺失的元素,以及哪些不在列表中。下面的代碼是正確和有效的方法嗎?我無法爲此使用任何外部庫。

我需要在兩種方式比較我的兩個數組列表。

  • 如果數據在源代碼中但實際上不是,則返回false並打印出缺少的元素。
  • 如果數據是實際但不在源中,那麼也返回false並打印出缺失的元素。

下面是我的代碼:

public static boolean compare(List<Task> source, List<Task> actual) { 
    List<Task> matchedTasksList = new ArrayList<Task>(); 
    List<Task> differedTasksList = new ArrayList<Task>(); 

    List<Task> copyOfSource = new ArrayList<>(source); 
    List<Task> copyOfActual = new ArrayList<>(actual); 
    for (Task o : actual) { 
     if (!copyOfSource.remove(o)) { 
     differedTasksList.add(o); 
     System.out.println("Task not present: " + o.toString()); 
     return false; 
     } else { 
     matchedTasksList.add(o); 
     } 
    } 
    matchedTasksList.clear(); 
    for (Task o : source) { 
     if (!copyOfActual.remove(o)) { 
     differedTasksList.add(o); 
     System.out.println("Task not present: " + o.toString()); 
     return false; 
     } else { 
     matchedTasksList.add(o); 
     } 
    } 
    return (differedTasksList.size() == 0) ? true : false; 
    } 
+0

你寫道:「可以有重複以及ArrayList中。」這是否意味着一個ArrayList可以多次包含相同的任務?這些是相同的Task對象,還是具有相同數據的不同Task對象?另外,如果'source'包含一個任務兩次,'actual'包含一次,那麼這是否意味着'actual'是任務一次的「丟失」? – jason44107

+0

這是一個具有相同數據的不同任務對象,而且實際上是缺少該任務一次。而且它也必須是雙向比較。 – user1234

+0

使用HashSets代替的ArrayList(更有效的去除+重複的)和使用的方法retainAll和所述的removeAll接口https://docs.oracle.com/javase/7/docs/api/java/util/Set.html的 – toongeorges

回答

2
public boolean compare(List<Task> source, List<Task> actual) { 
    Set<Task> intersection = new HashSet<>(source); 
    Set<Task> sourceDifference = new HashSet<>(source); 
    Set<Task> actualDifference = new HashSet<>(actual); 

    intersection.retainAll(actualDifference); 

    sourceDifference.removeAll(intersection); 
    for (Task t: sourceDifference) { 
     System.out.println(String.format("Task %s not present in actual", t)); 
    } 

    actualDifference.removeAll(intersection); 
    for (Task t: actualDifference) { 
     System.out.println(String.format("Task %s not present in source", t)); 
    } 

    return sourceDifference.isEmpty() && actualDifference.isEmpty(); 
} 
+0

你可以考慮使用https://docs.oracle.com/javase/7/docs/api/java/util/LinkedHashSet.html而不是HashSet的,如果在任務所記錄的順序是非常重要的 – toongeorges

+0

我們如何在這裏使用LinkedHashSet?你能否相應地更新,以便我能理解? – user1234

+0

而不是 '設置 sourceDifference = new HashSet <>(source); 設置 actualDifference = new HashSet <>(actual);' 你寫 '設置 sourceDifference = new LinkedHashSet <>(source); 設置 actualDifference =新LinkedHashSet <>(實際);' 僅當元素的順序事項做到這一點,因爲一個HashSet比用於插入和刪除一LinkedHashSet更高效 – toongeorges

0

好像是函數只打印第一遺漏的元素,但我瞭解你需要打印所有缺少的元素,並返回false?如果是這樣嘗試了這種方式:

public boolean compare(List<Task> source, List<Task> actual) { 
     List<Task> copyOfSource = new ArrayList<>(source); 
     copyOfSource.removeAll(actual); 
     copyOfSource.forEach(o -> System.out.println("Task not present: "+o.toString())); 
     return copyOfSource.isEmpty(); 
    } 
+0

我正在使用Java 7,你可以相應地編輯它嗎?它是否和我在我的問題中提到的那樣進行雙向比較?看到我更新的問題。 – user1234

+0

如果源有4個元素並且實際有5個元素,則會失敗。 – user1234

+0

我喜歡@ toongeorges的回答 –