2014-09-10 60 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