发现两个列表之间的区别

时间:2014-09-10 11:56:05

标签: java guava apache-commons apache-commons-collection

在java中假设我有2个列表

List<Object1> list1
List<Object2> list2

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

有没有办法比较名称并获得两个列表

的区别

这些2个对象是在第三方库中定义的,我不能覆盖等于和比较方法

我赞成googles Guava或commons集合库

Sets.symmetricDifference(Set1, Set2)要求传入2, 甚至我juse Sets.newHashSet(lis1)和Sets.newHashSet(lis2)来创建两个集合 但他们仍然在集合中有不同类型的对象。

或在公共CollectionUtils.disjunction(lis1, list2)中,列表仍然必须包含相同的对象类型

没有做2个昂贵的for循环,还有其他方法吗?

3 个答案:

答案 0 :(得分: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())来电。

答案 1 :(得分:0)

使用番石榴,试试这个。它适用于我 - &gt;

Multisets.difference(multiset1,multiset2);

如何将ArrayList转换为Multiset。

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

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

答案 2 :(得分:0)

首先,您必须将列表转换为基于字符串的列表:

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

必须对Object2进行相同的转换

然后转换输入列表:

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

// list1是Object1上的List

然后创建multiset:

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

然后只需:

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

这将为您提供差异以及差异的次数

如果您需要知道只是差异,那么执行相同的转换,然后在Set adn中加载字符串Collection,然后执行Sets.symmetricDifference