2015-03-13 36 views
1

我有兩個集合,它們都由相同類型的對象組成,這種類型的對象有一個字段,在本例中爲'codeType'。使用新的Java 8 API流和lambda表達式檢查兩個集合

我需要檢查在第二個集合中,所有'codeTypes'與第一個集合中的相同,沒有額外添加。我可以這樣做,只是迭代兩個集合以獲取id,然後檢查它們。 但是當我們使用的是Java 8,我想用流和lambda表達式(因爲我學習吧)

這是迄今爲止我所做的一切它做的事:

Boolean collectionEquals = CollectionUtils.isNotEmpty(oldOrderPositions) 
    ? oldOrderPositions.stream() 
         .mapToLong(oldPosition -> 
            oldPosition.getCodeType().getId()) 
         .allMatch(newOrderPositions.stream() 
                .mapToLong(newPosition -> 
                   newPosition.getCodeType().getId())) 
    : false; 

基本上我獲取兩個集合,我遍歷它們以獲取Id,然後檢查所有id的匹配。然而,我收到一個編譯錯誤,說「LongMream中的allMatch(java.util.fuction.Predicate)不能應用於(java.util.stream.LongStream)」

你能幫我嗎?我不知道我在做什麼錯,或者我在誤會。

謝謝您的時間

+1

我覺得你正在重塑車輪..請使用這樣的Google guava項目之一http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/ collect/Iterables.html#elementsEqual(java.lang.Iterable,java.lang.Iterable) – rakpan 2015-03-13 10:55:14

+0

@FirstX爲什麼他應該爲這個簡單的問題使用一個庫? – dit 2015-03-13 11:01:27

+0

@dit因爲它不是**「簡單的問題」。這是一個不平凡的比較操作,並且流並不適合這種情況。使用一個庫來完成你想要的(和正確的)是最好的創建一個DIY竊聽效用方法 – Vogel612 2015-03-13 11:13:12

回答

3

其他解決方案或者不檢查雙重或順序。

有了這個解決方案,您可以檢查所有的ID都存在,如果事件有杜布隆不管他們的立場:

return Arrays.equals(
    oldOrderPositions.stream() 
     .mapToLong(p -> p.getCodeType().getId()) 
     .sorted() 
     .toArray(), 
    newOrderPositions.stream() 
     .mapToLong(p -> p.getCodeType().getId()) 
     .sorted() 
     .toArray() 
); 

當然,你可以重構這個有方法做了變換,但因爲我不知道oldOrderPositionsnewOrderPositions是否屬於同一類型,所以我沒有自己做。如果是這樣,只要這樣做:

static long[] normalize(Collection<OrderPosition> orderPositions) { 
    return orderPositions.stream() 
     .mapToLong(p -> p.getCodeType().getId()) 
     .sorted() 
     .toArray(); 
} 
... 
return Arrays.equals(
    normalize(oldOrderPositions), 
    normalize(newOrderPositions) 
); 

哦,是的,你寫,你想使用的流來做到這一點。我不得不說,只因爲你有一把錘子,你不會把所有東西都放在牆上。有時你需要一把螺絲刀。所以這是一個解決方案,使用合適的工具來解決相應的問題。流對於問題的一部分(轉換)很有用,但爲了進行比較,我建議您採用其他一些好的工具,因此可以使用Arrays.equals()

+0

完全瞭解你在說什麼,謝謝。無論如何,我在頁面的頂部看到,如果已經是項目的依賴項,我推薦番石榴(我從來沒有用過),我只是檢查過它。你的解決方案是優雅的,我喜歡它,但你會推薦使用番石榴然後通過這個解決方案,或相反? – fgonzalez 2015-03-13 12:28:00

+1

這是個人選擇的問題。與Guava一起使用解決方案的好處是,您無需測試此代碼的責任,並且確信它可以按預期工作。如果你使用番石榴,你最好使用兩個'Multiset '並比較那些,而不是'Iterables.elementEquals()'(然後成爲Kocko的答案)。另一方面,在這裏你有一個完整的解決方案提供給你的確切用例,這是你的電話。缺點是要確保完全匹配,您必須對多頭進行排序。如果你的清單不是很大,這是一個不錯的解決方案。如果沒有,請使用番石榴。 – 2015-03-13 12:41:51

-1

一個Predicate必須採取Stream分量和返回true或false。你可能打算這樣做:

public void test() { 
    Collection<String> oldOrderPositions = new ArrayList<String>(); 
    Collection<String> newOrderPositions = new ArrayList<String>(); 
    Boolean collectionEquals = oldOrderPositions 
      .stream() 
      .allMatch(code -> newOrderPositions.contains(code)); 
} 

在這裏,我們將流和孩子堅持他們所有的謂語newOrderPositions.contains匹配 - 即孩子的每一個也是新的。

請注意,我通過使用Collection<String>大大簡化了您的機制。

+1

這個答案否定了問題中所有特別複雜的部分,即1.變換,2.需要在類型之間切換,3.列表類比較,而不是集合類比較。 – 2015-03-13 11:28:30

+0

@OlivierGrégoire - 儘管如此,它處理的是真正的問題,它是爲什麼在LongStream中的錯誤說「allMatch(java.util.fuction.Predicate)不能應用於(java.util.stream.LongStream)」*答案是*使用Predicate *。 – OldCurmudgeon 2015-03-13 11:30:52

+1

不,這是我的觀點2:人特意要求比較多頭和你回答比較字符串(或任何你想要的對象),在這種情況下,我們特別需要一個' Predicate'。這個答案使用這個事實無處。 – 2015-03-13 11:34:09