2014-09-10 27 views
4

之間的差異假設我有2所列出發現在java中兩個列表

List<Object1> list1 
List<Object2> list2 

object1.getName(); returns a String 
object2.getName(); return a String 

有沒有辦法比較的名字,並獲得兩個列表

那些2個對象在規定的差異第三方庫,我不能覆蓋equals和方法的compareTo

我贊成谷歌番石榴或公共集合庫

但的要求2被傳入, 即使我使用Sets.newHashSet(lis1)和Sets.newHashSet(lis2)創建兩個集合 ,但它們在集合中仍具有不同類型的對象。

或公共CollectionUtils.disjunction(lis1, list2)名單仍然包含相同的對象類型

沒有做2昂貴的循環,還有沒有其他的辦法嗎?

+0

你的名單有多大? – 2014-09-10 15:22:24

+0

爲什麼for循環比任何其他解決方案都貴?除非你正在做一些非常聰明的並行執行,否則你將不得不精確地檢查和轉換每個對象一次。 – 2014-09-10 22:12:41

+0

不是真的傑夫,試着比較兩個對象列表,通常最終做兩次for循環與另一個for循環。 n * n + n * n。但是,基於這些列表創建地圖是n + n + n + n。我問這個問題,因爲我徘徊有沒有比4xns更好的解決方案 – 2014-09-11 08:59:24

回答

1

首先,我們將構建兩個映射,每個映射對應一個映射名稱。然後我們遍歷鍵集之間的差異,處理任何類型的對象都有這個名字。這些地圖讓我們避免在列表中掃描,尋找具有該名稱的對象。 (在使用Map而不是Multimap時,我依賴於the asker's comment on another answer,在每個列表中,名稱是唯一的。如果您仍在使用Java 7,請將方法引用替換爲Function實現。)

Map<String, Object1> map1 = Maps.uniqueIndex(list1, Object1::getName); 
Map<String, Object2> map2 = Maps.uniqueIndex(list2, Object1::getName); 
for (String name : Sets.difference(map1.keySet(), map2.keySet())) 
    processObject1(map1.get(name)); 
for (String name : Sets.difference(map2.keySet(), map1.keySet())) 
    processObject2(map2.get(name)); 

如果你想要做的是建立列表或設置對象恰好一個列表,processObject1processObject2只需將對象添加到集合。

uniqueIndex的迭代順序是輸入迭代,並difference返回具有相同的迭代順序作爲第一個參數一個setView,這樣你就可以處理他們出現在輸入列表的順序對象,如果訂單與你的問題有關。


的Java 8流基本上提供相同的功能:

Map<String, Object1> map1 = list1.stream().collect(Collectors.toMap(Function.identity(), Object1::getName)); 
Map<String, Object2> map2 = list2.stream().collect(Collectors.toMap(Function.identity(), Object2::getName)); 
map1.keySet().stream().filter(n -> !map2.keySet().contains(n)).map(map1::get).forEachOrdered(o1 -> processObject1(o1)); 
map2.keySet().stream().filter(n -> !map1.keySet().contains(n)).map(map2::get).forEachOrdered(o2 -> processObject1(o2)); 

同樣,你可以更換forEachOrdered呼叫與collect(Collectors.toList()),如果你只是想收集的對象。

+0

最接近的答案我可以得到,Java 8是非常方便的方式。 – 2014-09-18 16:22:45

0

使用番石榴,試試這個。它適用於我 - >

Multisets.difference(multiset1,multiset2); 

如何將ArrayList轉換爲Multiset。

List x = new ArrayList(); 
x.add(3);..... 

Multiset newX = HashMultiset.create(); 
newX.addAll(x); 
+0

如何將ArrayList轉換爲multiset? – 2014-09-10 12:26:40

+0

編輯了答案幷包含了如何將數組列表轉換爲多重集。 – 2014-09-10 15:16:59

0

首先,你將不得不transfor您的列表,以基於字符串列表:

private static final class FromObject1ToName implements Function<Object1, String> { 
    @Override 
    public String apply(Object1 input) { 
     return input.name; 
    } 
} 

相同的變換有對象2

然後變換輸入列表:

Collection<String> transformed = Collections2.transform(list1, new FromObject1ToName()); 

// list1是Object1上的列表

然後創建多集:

Multiset<String> multiset1 = HashMultiset.create(); 
    multiset1.addAll(transformed); 

後來乾脆:

Multisets.difference(multiset1, multiset2) // multiset1 is from Object1 and multiset2 is from Object2 

這會給你的區別,它多少次differes

如果您需要了解只是差異,然後做相同的轉換,然後加載字符串集合在一個集合然後做Sets.symmetricDiffe rence

+0

感謝,它很酷,但是一旦我得到了一組字符串的區別,我仍然需要遍歷列表中的每個元素來獲取實際的object1或object2。我徘徊有沒有更好的辦法做到這一點 – 2014-09-10 14:50:40

+0

@山陽區你的輸入列表是否可以包含多個相同的名字?我的意思是,由Object1實例組成的輸入列表可以有兩個具有相同名稱的對象? – Eugene 2014-09-10 17:19:05

+0

在這兩個列表中都可以有相同的名稱,但在它自己的列表中,名稱應該是唯一的 – 2014-09-11 08:54:21