如何返回两个列表之间的差异?

我有两个数组列表。

List<Date> a;
contains : 10/10/2014, 10/11/2016


List<Date> b;
contains : 10/10/2016

如何在列表 ab之间进行检查,以便返回在 b中丢失的值。10/10/2014

185334 次浏览

您可以将它们转换为 Set集合,并对它们执行集合差异操作。

像这样:

Set<Date> ad = new HashSet<Date>(a);
Set<Date> bd = new HashSet<Date>(b);
ad.removeAll(bd);

如果只想找到 b 中缺失的值,可以这样做:

List toReturn = new ArrayList(a);
toReturn.removeAll(b);


return toReturn;

如果你想找出列表中的值,你可以执行上面的代码两次。更改了名单。

我正在寻找一个不同的问题,遇到了这个问题,所以我将添加我的解决方案到一个相关的问题: 比较两个地图。

    // make a copy of the data
Map<String,String> a = new HashMap<String,String>(actual);
Map<String,String> e = new HashMap<String,String>(expected);
// check *every* expected value
for(Map.Entry<String, String> val : e.entrySet()){
// check for presence
if(!a.containsKey(val.getKey())){
System.out.println(String.format("Did not find expected value: %s", val.getKey()));
}
// check for equality
else{
if(0 != a.get(val.getKey()).compareTo(val.getValue())){
System.out.println(String.format("Value does not match expected: %s", val.getValue()));
}
// we have found the item, so remove it
// from future consideration. While it
// doesn't affect Java Maps, other types of sets
// may contain duplicates, this will flag those
// duplicates.
a.remove(val.getKey());
}
}
// check to see that we did not receive extra values
for(Map.Entry<String,String> val : a.entrySet()){
System.out.println(String.format("Found unexpected value: %s", val.getKey()));
}

它的工作原理与其他解决方案相同,而且不仅比较存在的值,而且比较它们包含相同的值。大多数情况下,我在会计软件中使用这种方法来比较两个来源的数据(员工和经理输入的价值匹配; 客户和公司交易匹配; 等等)

你可以使用来自 Apache Commons Collections4.0的 CollectionUtils:

new ArrayList<>(CollectionUtils.subtract(a, b))

您可以在 Java8Stream库中使用 filter

List<String> aList = List.of("l","e","t","'","s");
List<String> bList = List.of("g","o","e","s","t");


List<String> difference = aList.stream()
.filter(aObject -> {
return ! bList.contains(aObject);
})
.collect(Collectors.toList());


//more reduced: no curly braces, no return
List<String> difference2 = aList.stream()
.filter(aObject -> ! bList.contains(aObject))
.collect(Collectors.toList());

System.out.println(difference);测试结果:

[ e,t,s ]

您可以在 下划线-java库中调用 Underscore.difference(lists)方法

import com.github.underscore.Underscore;
import java.util.Arrays;
import java.util.List;


public class Main {
public static void main(String[] args) {
List<Integer> list1 = Arrays.asList(1, 2, 3);
List<Integer> list2 = Arrays.asList(1, 2);
List<Integer> list3 = Underscore.difference(list1, list2);
System.out.println(list3);
// [3]
}
}

我看起来很相似,但是我希望两个列表(两个列表之间不常见的元素)有所不同。

假设我有:

List<String> oldKeys = Arrays.asList("key0","key1","key2","key5");
List<String> newKeys = Arrays.asList("key0","key2","key5", "key6");

我想知道哪个键已经被添加,哪个键被删除,即我想得到 (key1, key6)

使用 org.apache.commons.collections.CollectionUtils

List<String> list = new ArrayList<>(CollectionUtils.disjunction(newKeys, oldKeys));

结果

["key1", "key6"]

首先将列表转换为集合。

// create an empty set
Set<T> set = new HashSet<>();


// Add each element of list into the set
for (T t : list)
set.add(t);

您可以使用 Sets.difference(Set1, Set2),它返回 Set1中存在的额外项。
您可以使用 Sets.difference(Set2, Set1),它返回 Set2中存在的额外项。

List<String> l1 = new ArrayList<String>();
l1.add("apple");
l1.add("orange");
l1.add("banana");
l1.add("strawberry");


List<String> l2 = new ArrayList<String>();
l2.add("apple");
l2.add("orange");


System.out.println(l1);
System.out.println(l2);


for (String A: l2) {
if (l1.contains(A))
l1.remove(A);
}


System.out.println("output");
System.out.println(l1);

产出:

[apple, orange, banana, strawberry]
[apple, orange]
output
[banana, strawberry]

下面是这个问题的通用解决方案。

public <T> List<T> difference(List<T> first, List<T> second) {
List<T> toReturn = new ArrayList<>(first);
toReturn.removeAll(second);
return toReturn;
}

使用 Stream API,您可以执行以下操作:

List<String> aWithoutB = a.stream()
.filter(element -> !b.contains(element))
.collect(Collectors.toList());


List<String> bWithoutA = b.stream()
.filter(element -> !a.contains(element))
.collect(Collectors.toList());


Set 是下面的一张地图我能够得到两个超过一百万条目的差异每个包装它在一个 HashSet 这是一个简单的代码做到这一点。

private List<String>notPresentMethod(final List<String>left,final List<String>right){
final Set<String>setIsFaster = new HashSet<>(right);
return left.stream()
.filter(((Predicate<String>)setIsFaster::contains).negate())
.collect(Collectors.toList());
}

仅使用列表花了一个多小时,没有完成。使用这个样本只花了几秒钟。