Jun*_*Liu 5 java apache-commons guava apache-commons-collection
在java中假设我有2个列表
List<Object1> list1
List<Object2> list2
object1.getName(); returns a String
object2.getName(); return a String
Run Code Online (Sandbox Code Playgroud)
有没有办法比较名称,并得到两个列表的差异
这些2个对象在第三方库中定义,我不能覆盖equals和compareto方法
我赞成googles Guava或commons集合库
但Sets.symmetricDifference(Set1, Set2)要求传入2,即使我使用Sets.newHashSet(lis1)和Sets.newHashSet(lis2)创建两个集合,但它们仍然在集合中具有不同类型的对象.
或者在公共中CollectionUtils.disjunction(lis1, list2),列表仍然必须包含相同的对象类型
没有做2个昂贵的for循环,还有其他方法吗?
首先,我们将构建两个映射,每个列表一个,将名称映射到对象。然后我们迭代键集之间的差异,处理具有该名称的任何类型的对象。这些地图让我们避免扫描列表来寻找具有该名称的对象。(在使用 Map 而不是 Multimap 时,我依赖提问者对另一个答案的评论,即每个列表中的名称都是唯一的。如果您仍在使用 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));
Run Code Online (Sandbox Code Playgroud)
如果您只想在一个列表中构建列表或对象集,processObject1并且processObject2只需将对象添加到集合中即可。
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));
Run Code Online (Sandbox Code Playgroud)
同样,如果您只想收集对象,则可以将调用替换forEachOrdered为。collect(Collectors.toList())
| 归档时间: |
|
| 查看次数: |
3387 次 |
| 最近记录: |