如何返回两个列表之间的差异?
Posted
技术标签:
【中文标题】如何返回两个列表之间的差异?【英文标题】:How can I return the difference between two lists? 【发布时间】:2015-01-16 03:31:46 【问题描述】:我有两个数组列表,例如
List<Date> a;
contains : 10/10/2014, 10/11/2016
List<Date> b;
contains : 10/10/2016
如何在列表 a
和 b
之间进行检查,以便返回 b
中缺少的值?例如10/10/2014
【问题讨论】:
guava 有一些不同的工具,但它适用于Set
,我认为removeAll
可能适合你
复制列表a
。从副本中删除所有出现在b
中的元素。
docs.oracle.com/javase/7/docs/api/java/util/…
如果你想要两者之间的析取,CollectionUtil 有一个析取方法可以返回差值。
这可能是指来自 Apache Commons Collections 的 CollectionUtils.subtract
;有关详细信息,请参阅this answer。
【参考方案1】:
您可以将它们转换为Set
集合,并对它们执行集差操作。
像这样:
Set<Date> ad = new HashSet<Date>(a);
Set<Date> bd = new HashSet<Date>(b);
ad.removeAll(bd);
【讨论】:
removeAll
返回 boolean
而不是 Set
没错,但是当您查看文档时,您会看到此布尔值告知“此集合是否因调用而更改”。进行此更改后,您可以访问 Set,您会注意到它具有您预期的结果。
创建bd
HashSet
是不必要的。您可以拨打ad.removeAll(b)
。
如果 bd 的元素比 ad 多怎么办?在那种情况下会发生什么?【参考方案2】:
如果你只想找到b中的缺失值,你可以这样做:
List toReturn = new ArrayList(a);
toReturn.removeAll(b);
return toReturn;
如果您想找出任一列表中存在的值,您可以执行上面的代码两次。使用更改的列表。
【讨论】:
如果它的列表不可修改怎么办? 由于您创建了一个新列表,这也适用于不可修改的列表。【参考方案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"]
【讨论】:
你能不能把我指向 maven 存储库。我试过这个https://mvnrepository.com/artifact/org.apache.commons/commons-collections4/4.4
但它似乎不是正确的。
@paradocslover 它是mvnrepository.com/artifact/commons-collections/…
非常感谢!!知道在新版本的包中重命名的函数是什么吗?【参考方案4】:
您可以在 Java 8 Stream
库中使用 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]
【讨论】:
谢谢陌生人!【参考方案5】:您可以使用 Apache Commons Collections 4.0 中的 CollectionUtils:
new ArrayList<>(CollectionUtils.subtract(a, b))
【讨论】:
注意:这种方法不以任何方式支持泛型,所以你得到的是一个原始的、未经检查的Collection
实例。
方法签名是:public static <O> Collection<O> subtract(Iterable<? extends O> a, Iterable<? extends O> b)
,根据文档:“O - 能够表示两个输入集合中包含的类型的泛型类型。”
你确实是对的;过失。我正在查看该类的 3.2 版本,其中该方法具有简单的 public static Collection subtract(final Collection a, final Collection b)
签名。很高兴看到他们在 4.0 迭代中对此进行了改进。【参考方案6】:
首先将列表转换为集合。
// 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 中存在的额外项目。
【讨论】:
哇,不错的解决方案。我从来不知道这门课【参考方案7】:使用 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());
【讨论】:
【参考方案8】:这里是这个问题的通用解决方案。
public <T> List<T> difference(List<T> first, List<T> second)
List<T> toReturn = new ArrayList<>(first);
toReturn.removeAll(second);
return toReturn;
【讨论】:
这在大多数情况下都会派上用场。谢谢!!【参考方案9】: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]
【讨论】:
【参考方案10】:您可以在underscore-java 库中调用Underscore.difference(lists)
方法。 Live example
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]
【讨论】:
如果 list2 还包含一些额外的值怎么办。 list2 = 1,2,4,5。预期列表 3 = 3,4,5【参考方案11】:我一直在寻找一个不同的问题并遇到了这个问题,所以我将把我的解决方案添加到一个相关的问题:比较两个地图。
// 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()));
它的工作原理与其他解决方案相同,但不仅比较存在的值,而且比较它们包含相同的值。在比较来自两个来源的数据(员工和经理输入的值匹配;客户和公司交易匹配;...等)时,我主要在会计软件中使用它
【讨论】:
我不知道有关地图的问题。如果您发现有关地图的问题,请随时链接到此答案。 答案应解决所提出的问题。如果您认为您有一个有用的代码 sn-p / 解释某些不存在问题的东西,请自己提出问题并使用内置的站点功能自行回答。不要在不相关的问题下发布您的答案。 我的回答和问题的区别不在于Map
vs List
的使用。不同之处在于仅要求缺失值的问题,我解决了值的“缺失、添加和相等”。如果寻求答案的人看不到 Map
、Set
和 List
是相关概念的方式,我会担心。【参考方案12】:
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());
仅使用列表需要一个多小时,但没有完成。使用此示例只需几秒钟。
【讨论】:
以上是关于如何返回两个列表之间的差异?的主要内容,如果未能解决你的问题,请参考以下文章
如何以毫秒为单位获得两个 QDateTimes 之间的差异?