C# 中的IComparable和IComparer的使用及区别
作者:HueiFeng 发布时间:2023-04-19 20:11:55
前言
在开发过程中经常会遇到比较排序的问题,比如说对集合数组的排序等情况,基本类型都提供了默认的比较算法,如string提供了按字母进行排序,而int整数则是根据整数大小进行排序.但是在引用类型中(具有多个字段),那么这个排序当然也是取决于我们特定的值。
IComparable接口
该接口由其值可以排序或排序的类型实现,并提供强类型的比较方法以对泛型集合对象的成员进行排序,例如数字可以大于第二个数字,一个字符串可以在另一个字符串之前以字母顺序出现。他要求实现类型定义的一个方法,CompareTo(T)该方法指示当前实现在排序顺序中的位置是在同一个类型和第二个对象之前、之后还是与其相同。通常,不会直接从开发人员代码中调用方法。相反他由List.Sort()和Add等方法自动调用。
通常,提供Icomparable实现的类型还IEquatable实现接口。IEquatable接口Equals定义方法,该方法确定实现类型的实例的相等性。
CompareTo(T)方法的实现必须Int32返回具有以下三个值之一的,如下表所示。
值 | 含义 |
---|---|
小于零 | 此对象在排序顺序中位于CompareTo方法所指定的对象之前。 |
零 | 此当前实例在排序顺序中与CompareTo方法参数指定的对象出现在同一位置。 |
大于零 | 此当前实例位于排序顺序中由CompareTo方法自变量指定的对象之后。 |
示例:
class Student : IComparable
{
public string Name { get; set; }
public int Age { get; set; }
public int CompareTo(object obj)
{
if (!(obj is Student))
{
throw new ArgumentException("Compared Object is not of student");
}
Student student = obj as Student;
return Age.CompareTo(student.Age);
}
}
Ps:我们根据通过Age(int)来进行我们的排序
执行测试
class Program
{
static void Main(string[] args)
{
ArrayList studentList = new ArrayList {
new Student{Name="a",Age=9 },
new Student{Name="a3",Age=7 },
new Student{Name="a1",Age=6 },
new Student{Name="a2",Age=10 },
};
studentList.Sort();
StudentComparable(studentList);
Console.ReadLine();
}
private static void StudentComparable(ArrayList studentList)
{
foreach (Student item in studentList)
{
Console.WriteLine("Name:{0},Age:{1}", item.Name, item.Age);
}
}
}
输出如下
IComparer接口
IComparable 接口的CompareTo方法一次只能对一个字段进行排序,因此无法对不同的属性进行排序。IComparer接口提供了Compare方法,该方法比较两个对象并返回一个值,该值指示一个对象小于,等于或大于另一个对象。实现IComparer接口的类必须提供比较两个对象的Compare方法。例如,您可以创建一个StudentComparer类,该类实现IComparer,并具有一个Compare方法,该方法按Name比较Student对象。然后,您可以将StudentComparer对象传递给Array.Sort方法,它可以使用该对象对Student对象的数组进行排序。
示例
class StudentComparer : IComparer
{
public int Compare(object x, object y)
{
Student x1 = x as Student;
Student y1 = y as Student;
return x1.Name.CompareTo(y1.Name);
}
}
Ps:我们根据Name(string)进行排序
执行测试
class Program
{
static void Main(string[] args)
{
ArrayList studentList = new ArrayList {
new Student{Name="a",Age=9 },
new Student{Name="a3",Age=7 },
new Student{Name="a1",Age=6 },
new Student{Name="a2",Age=10 },
};
studentList.Sort(new StudentComparer());
StudentComparable(studentList);
Console.ReadLine();
}
private static void StudentComparable(ArrayList studentList)
{
foreach (Student item in studentList)
{
Console.WriteLine("Name:{0},Age:{1}", item.Name, item.Age);
}
}
}
输出结果如下
IComparable 和IComparer
上述示例中我们将对象进行了多次的装箱和拆箱,那么此时我们可以将方法改为泛型的,泛型的出现也让我们避免了装箱和拆箱的资源浪费.
最终我们实现的代码片段如下:
IComparable
class Student : IComparable<Student>
{
public string Name { get; set; }
public int Age { get; set; }
public int CompareTo([AllowNull] Student other)
{
return Age.CompareTo(other.Age);
}
}
IComparer
class StudentComparer : IComparer<Student>
{
public int Compare([AllowNull] Student x, [AllowNull] Student y)
{
return x.Name.CompareTo(y.Name);
}
}
总结
参考: https://docs.microsoft.com/en-us/dotnet/api/system.icomparable-1?view=netframework-4.8
示例: https://github.com/hueifeng/BlogSample/tree/master/src/CompareDemo
来源:https://www.cnblogs.com/yyfh/p/12129000.html
猜你喜欢
- 冒泡排序法:关键字较小的记录好比气泡逐趟上浮,关键字较大的记录好比石块下沉,每趟有一块最大的石块沉底。算法本质:(最大值是关键点,肯定放到最
- 为什么要限流系统在设计的时候,我们会有一个系统的预估容量,长时间超过系统能承受的TPS/QPS阈值,系统有可能会被压垮,最终导致整个服务不可
- 1.内部类概念及分类将一个类定义在另一个类的内部或者接口内部或者方法体内部,这个类就被称为内部类,我们不妨将内部类所在的类称为外围类,除了定
- 简介最近几年,各种新的高效序列化方式层出不穷,不断刷新序列化性能的上限,最典型的包括:专门针对Java语言的:Kryo,FST等等跨语言的:
- 本文以一个简单实例讲述了C#装箱和拆箱操作的实现方法,简单来说装箱是将值类型转换为引用类型;拆箱是将引用类型转换为值类型,是涉及栈和堆的使用
- 本文实例为大家分享了Java实现五子棋游戏的具体代码,供大家参考,具体内容如下一、功能分析五子棋的实现还是较为简单的,通过下期的流程我们可以
- 前言任何一个服务如果没有监控,那就是两眼一抹黑,无法知道当前服务的运行情况,也就无法对可能出现的异常状况进行很好的处理,所以对任意一个服务来
- java @Value("${}")获取不到配置文件中值1、property.yml配置spring: ma
- 1 pom.xml文件注:热部署功能spring-boot-1.3开始有的<!--添加依赖--><dependency&g
- SpringBoot接收文件和对象使用场景:某个接口,需要同时接收文件和实体,也就是参数一、这个时候,前端就不能json格式传送数据了,要用
- 关于 LoadLibrary 的疑问Win32 API 中 LoadLibrary 函数的功能是加载某个库文件(通常是 dll 文件),然后
- 要将一个对象序列化,可是如果对象的属性为null的时候,我们想将属性为null的都去掉。在这里我使用Newtonsoft.Json.dll记
- 下面通过图文并茂的方式给大家分享C#实现KTV点歌系统。public enum SongPlayState { //未播放,播放
- 一.MyBatis简介1)MyBatis 是一款优秀的持久层框架2)MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结
- 两张表SystemParam(系统参数表) Suit (主题)SystemParam 与 Suit 是多对一Suit 的higerSuit字
- 前面讲解了MediaPlayer播放网络音频,主要介绍了MediaPlayer关于网络音频的缓冲和进度条控制的方法,本文再来讲解一下Medi
- 一、 Spring Bean 配置方式由 Spring IoC 容器管理的对象称为 Bean,Bean 配置方式有两种:配置文件开发和注解开
- 说明:曾经在网上看过花样繁多的分页,很多都号称如何通用,但很多时候往往不尽如人意:有在分页类中还加入URL地址信息的,有在分页类中还进行分页
- 今天来研究的是ScrollView-滚动视图,滚动视图又分横向滚动视图(HorizontalScrollView)和纵向滚动视图(Scrol
- 目录引言SqlSessionFactory不使用 XML 构建 SqlSessionFactorySqlSessionFactoryBuil