2017-08-09 129 views
-2

我有一個類的字段日期,ID和行動。在我的情況下,我有舊項目列表和另一個列表,其中包括舊項目和新項目,所以我想過濾舊項目,所以我不介意他們。例如,我遍歷新項目,只使用不屬於舊項目列表的項目。列表的Java流差異

隨着循環,它看起來是這樣,但我想

List<Item> filteredList = new ArrayList<>(); 
    for (Item item : newList) { 
     for (Item oldItem : oldList) { 
      if (!item.getDate().equals(oldItem.getDate()) && !item.getId().equals(oldItem.getId()) && !item.getAction().equals(oldItem.getAction())) { 
       filteredList.add(item); 
      } 
     } 
    } 
+5

爲什麼「每個人總是」試圖使用流沒有任何理由,除了「他們很酷和臀部」沒有任何實際的要求/使用?也許看看數據流是如何工作的以及它們提供了什麼功能,但你並沒有表現出將自己的循環移植到數據流上的任何努力。 – luk2302

+4

如果你想從一個列表中刪除其他列表中的項目,你總是可以使用'list.removeAll(otherList)'。只要確保您的項目可以用equals方法進行適當的比較。 – Pshemo

回答

3

首先,我建議實施一個equals方法功能性的方式重寫它在你的Item類,以避免複雜的條件(這我不確定是否正確,BTW)。

其次,爲了使搜索更有效率,將舊列表的元素放在HashSet中,以允許持續時間查找。這將需要覆蓋Item類的equalshashCode

最後的代碼如下所示:

List<Item> filteredList = 
    newList.stream() 
      .filter(i -> !oldList.contains(i)) // oldList should be replaced with a HashSet 
               // for better performance 
      .collect(Collectors.toList()); 

隨着HashSet

Set<Item> oldSet = new HashSet<>(oldList); 
List<Item> filteredList = 
    newList.stream() 
      .filter(i -> !oldSet.contains(i)) 
      .collect(Collectors.toList()); 

關於你的病情:

if (!item.getDate().equals(oldItem.getDate()) && !item.getId().equals(oldItem.getId()) && !item.getAction().equals(oldItem.getAction())) 

看來錯了,因爲如果有兩個不同的項目ID將具有相同的日期(或行動),他們將通過測試。

我相信你打算寫:

if (!item.getDate().equals(oldItem.getDate()) || !item.getId().equals(oldItem.getId()) || !item.getAction().equals(oldItem.getAction())) 

這意味着,如果他們在3種性質相差至少一個兩個項目彼此認爲是不同的。所有的

2

首先應實現equals()方法(和.hashCode()也一樣)在Item類,因此你可以正確地比較項目,例如,它會使用List.contains() method時需要。

然後,您可以使用.contains()方法來測試當前項目是否存在於oldList中,並根據該結果過濾項目。

與Java 8的代碼應該是這樣的:

List<Item> result = newList.stream()     
     .filter(line -> !oldList.contains(line))  
     .collect(Collectors.toList()); 

注:

注意的是,使用stream這裏是不是真的有必要,你可以只實現這個使用List方法,如.retainAll()這將允許您以更好的方式過濾newList

+0

應該注意的是,如果你實現了equals,那麼你也必須實現hashCode! –

+1

@ Absurd-Mind謝謝你指出。當然,'.hashCode'應該和'.equals()'一起實現。 –

1

您不需要流來執行此任務。只要使用List.removeAll方法,這不正是你想要什麼:

oldList.removeAll(newList); 

這就要求Item類來實現equals()方法,所以元素可以進行比較,以平等和被移除。

如果你不想你的突變原oldList,您可以創建一個新的列表,然後從中刪除元素:

List<Item> filteredList = new ArrayList<>(oldList); 
filteredList.removeAll(newList); 

另一個功能更強大ISH方式做到這一點是通過使用該Collection.removeIf方法:

oldList.removeIf(item -> newList.contains(item)); 

或者只是:

oldList.removeIf(newList::contains); 

這仍然需要Item類來實現equals()方法。然而,這也將是低效的,因爲List.contains將需要遍歷整個newList以檢查每個項目oldList是否屬於它。更有效的方法是使用一個HashSet

Set<Item> newSet = new HashSet<>(newList); 

然後,如上使用removeIf

oldList.removeIf(newSet::contains); 

這種方法不僅需要Item類來實現equals()方法,也是hashCode方法,該方法在平等方面必須符合Object類合同。