一种集合“相等性”的实现

最近在工作中遇到了一个小的功能,就是需要向一个服务发送请求命令,需要判断请求是否发生变化,如果发生变化了,则重新请求。该问题实际上就是判断两个集合是否相等,只需要记录最后一次请求的元素的集合,然后将其和最新一次进行比较是否相等。需要说明的是这里定义的集合相等是指:两个集合如果元素值一样并且出现的次数也一样,即使顺序不一样也认为是相等,比如集合A={1,2,3,4,4,5} 集合B={1,4,4,2,3,5} 这两个集合也认为是相等的。后面讨论的集合相等都是基于这一假设的。

就这么个简单的问题,也有不同种解决方法,这里和大家分享一下。

方法一 使用Dictionary计数来实现

这种方法思路很简单,创建一个Dictionary对象,将第一个集合中的元素作为key添加到Dictionary中,value即为出现的次数。然后遍历第二个集合,如果包含相同的key,则value减1,如果不好含,则直接返回false,表示两个集合不同。最后,如果Dictionary中所有key对应的value都为0即表示两个集合相等,否则不相等。

/// <summary>/// 判断两个集合是否相等,相等 表示元素值及出现的次数一样即可,顺序可以不一样。/// </summary>/// <typeparam name="T"></typeparam>/// <param name="list1"></param>/// <param name="list2"></param>/// <returns></returns>public static bool ScrambledEquals<T>(IEnumerable<T> list1, IEnumerable<T> list2)
{//如果集合个数不相等,则集合不同    if (list1.Count() != list2.Count()) return false;var cnt = new Dictionary<T, int>();foreach (T s in list1)
    {if (cnt.ContainsKey(s))
        {
            cnt[s]++;
        }else        {
            cnt.Add(s, 1);
        }
    }foreach (T s in list2)
    {if (cnt.ContainsKey(s))
        {
            cnt[s]--;
        }else //如果第二个集合中有第一个集合中未包含的元素,表示两个集合不同        {return false;
        }
    }return cnt.Values.All(c => c == 0);
}

算法需要对象实现IEquatable接口,而该接口一般对象均默认实现。

以上算法的效率是很高的,时间复杂度为O(N),因为对Dictionary的查找时间复杂度为O(1),所以主要时间都花在遍历集合上。

以上方法对.NET不同的版本都兼容,如果是.NET 2.0版本也非常容易改造,只需要把最后一句代码改为遍历即可。由于项目原因,本人开发环境为2.0所以才用的是该方法。

方法二 使用IEnumerable的SequenceEqual 扩展方法

在.NET 3.5 中,比较集合元素的相等性有了新的方法,IEnumerable接口提供了名为SequenceEqual的方法,该方法用于判断两个序列是否顺序相等,即两个源序列的长度相等,且其相应元素相等。

我们可以先对两个集合进行排序,然后直接调用Enumerable.SequenceEqual 方法即可,这大概是最简单的实现方法了。

public static bool ScrambledEqualsUsingSequenceEqual<T>(IEnumerable<T> list1, IEnumerable<T> list2)
{return Enumerable.SequenceEqual(list1.OrderBy(t => t), list2.OrderBy(t => t));
}

需要注意的是,如果要自定义相等特性,需要实现IEquatable<T>接口,并提供自定义的Equal和GetHashCode实现。

方法三 使用CollectionAssert.AreEquivalent方法

在Visual Studio的单元测试框架中,位于Microsoft.VisualStudio.TestTools.UnitTesting命名空间下,以及在NUnit中都存在有CollectionAssert.AreEquivalent方法,该方法的解释是:

Two collections are equivalent if they have the same elements in the same quantity, but in any order. Elements are equal if their values are equal, not if they refer to the same object.

从定义可以看出 这正是我们定义的集合相等性。所以可以直接使用该方法。需要注意的是该命名空间位于Microsoft.VisualStudio.QualityTools.UnitTestFramework.dll这个dll中。

本栏目更多精彩内容:http://www.bianceng.cnhttp://www.bianceng.cn/Programming/net/

以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索集合
, dictionary
, 方法
, list集合的合并的问题
, ienumerable
, list集合比较
, 元素
, 判断相等
, 相等
, 两个
, 顺序表求集合问题
, 两个list集合比较
, 相等判断问题
不同
java判断两个集合相等、判断两个集合是否相等、集合相等、比较两个集合是否相等、证明两个集合相等,以便于您获取更多的相关知识。

时间: 2024-10-31 15:04:46

一种集合“相等性”的实现的相关文章

Java中的2种集合排序方法介绍_java

直接上代码: import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.List; /** * * <p> * ClassName CollectionsSort * </p> * <p> * Description 主要介绍两种集合的排序算法<br/> * 第一:java.util.Collections.s

VB.NET 中的2种集合

   //在  .NET种又2种集合 一种是 VB的 collection   集合 另一种是   .NET Framework 的泛型集合   ////VB的collection集合     和 .NET下的泛型集合 泛型集合限定了 键值对的类型 1.   VB的collection集合 Module Module1     Sub Main()         Dim col As New Microsoft.VisualBasic.Collection()         col.Add(

【hibernate框架】几种集合映射

1.Set 前面我们已经用过,就不再说. 2.List Group.java: package cn.edu.hpu.listMapping; import java.util.ArrayList; import java.util.List; import javax.persistence.CascadeType; import javax.persistence.Entity; import javax.persistence.FetchType; import javax.persist

Effective C#原则40:根据需求选择集合

"哪种集合是最好的?"答案是:"视情况而定." 不同的集合有不同的性能,而且在不同的行为上有不同的优化..Net框架支持很 多类似的集合:链表,数组,队列,栈,以及其它的一些集合.C#支持多维的数 组,它的性能与一维的数组和锯齿数组都有所不同..Net框架同样包含了很多特 殊的集合,在你创建你自己的集合类之前,请仔细参阅这些集合.你可以发现很 多集合很快,因为所有的集合都实现了ICollection接口.在说明文档中列出了 所有实现了ICollection接口的集合

java-对象管理-集合

在实际的项目开发中会有很多的对象,如何高效.方便地管理对象,成为影响程序性能与可维护性的重要环节.Java 提供了集合框架来解决此类问题,线性表.链表.哈希表等是常用的数据结构,在进行 Java 开发时,JDK 已经为我们提供了一系列相应的类来实现基本的数据结构,所有类都在 java.util 这个包里. Collection ├List │├LinkedList │├ArrayList │└Vector │ └Stack └Set Map ├Hashtable ├HashMap └WeakHa

Python数据结构之集合概览

Python数据结构之集合概览集合(collection),正如其名称所示,是可以作为概念性的单位来处理的一组零个或多个项.几乎软件的每一个重要部分都涉及集合的使用.尽管我们在计算机科学中所学的一些内容已经随着技术的变化逐渐消失,但组织集合的基本原理并没有变化.尽管集合在结构和用法上各不相同,但是,所有的集合都有着相同的基本作用,即帮助程序员有效地在程序中组织数据. 可以从两个视角来看待集合.集合的用户和客户关注它们在各种应用程序中能做些什么.集合的开发者和实现者关注它们作为通用资源的最佳性能.

Cookie集合基础

Cookies.Session和Application对象很类似,也是一种集合对象,都是用来在保存数据.但Cookies和其它对象最大的不同是Cookies 将数据存放于客户端的磁盘上,而Application 以及Session对象是将数据存放于Server端.Application.Section 以及Cookies 对象的差异如下表所示: 物件 数据存放位置 生命周期 Application Server 端的内存上. 终止于IIS 关闭时. Session 存放在Server 端的内存上

(教学思路 C#集合二)哈希表

这一节我们来学习第二种集合,因为它的特性,可以提供一种相当有效率的搜索方法,所以在实际项目中非常实用,它就是哈希表.哈希继 承了IDictionary接口,IDictionary接口提供了key(键)/value(值)集合设计模式,这种类集合中的每个一个对象都包含一个与它相对应的 key,可以通过所指定的key找到集合中所对应的对象(value值),这个接口最重要之处在于定义了公共属性Item.values.keys,其中Item根 据指定的key返回集合中所对应的值,values用来返回集合中

(教学思路 C#集合一)集合的概述、动态数组ArrayList

这一节我们来学习集合,什么是集合呢? 集合就如同数组,用来存储和管理一组特定类型的数据对象,除了基本的数据处理功能,集合直 接提供了各种数据结构及算法的实现,如队列.链表.排序等,可以让你轻易地完成复杂的数据操作.在使用数组和集合时要先加入 system.collections命名空间,它提供了支持各种类型集合的接口及类.集合本身上也是一种类型,基本上可以将其作为用来存储一组数据对 象的容器,由于c#面向对象的特性,管理数据对象的集合同样被实现成为对象,而存储在集合中的数据对象则被称为集合元素.