C#基础之数组排序,对象大小比较

原文链接:【OutOfMemory.CN

从个小例子开始:

1
2
3
int[] intArray = new int[]{2,3,6,1,4,5};
Array.Sort(intArray);
Array.ForEach<int>(intArray,(i)=>Console.WriteLine(i));

这个例子定义了一个int数组,然后使用Array.Sort(arr)静态方法对此数组进行排序,最后输出排序后的数组。以上例子将毫无意外的依次输出1,2,3,4,5,6.

为什么Array的Sort方法可以正确的对int数组进行排序呢,我们自定义类可以吗?试试看,如下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
public class Student
{
    public int Age { getset; }
 
    public string Name { getset; }
 
    public int Score { getset; }
}
 
 
 
static void Main(string[] args)
{
    Student[] students = new Student[]{
        new Student(){Age = 10,Name="张三",Score=70},
        new Student(){Age = 12,Name="李四",Score=97},
        new Student(){Age = 11,Name="王五",Score=80},
        new Student(){Age = 9,Name="赵六",Score=66},
        new Student(){Age = 12,Name="司马",Score=90},
    };
 
    Console.WriteLine("--------------默认排序输出--------");
    Array.Sort(students);
    Array.ForEach<Student>(students,(s)=>Console.WriteLine(string.Format("{0}{1,2}岁了,他的分数是{2,3}",s.Name,s.Age,s.Score)));
 
    Console.Read();
}

我们定义了Student类然后同样对他的数组进行排序,程序正确的编译通过,但是运行出错,运行时抛出了异常:System.InvalidOperationException{"Failed to compare two elements in the array."},这个异常的InnerException是ArgumentException{"At least one object must implement IComparable."};运行时异常说明:我们要使用Array.Sort(arr)静态方法,必须得保证数组中有一个元素实现IComparable接口。既然如此我们就让Student类实现IComparable接口.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public class Student :IComparable
{
    public int Age { getset; }
 
    public string Name { getset; }
 
    public int Score { getset; }
 
 
    /// <summary>
    /// 实现IComparable接口,用Age做比较
    /// </summary>
    /// <param name="obj">比较对象</param>
    /// <returns>比较结果</returns>
    public int CompareTo(object obj)
    {
        if (obj is Student)
        {
           return Age.CompareTo(((Student)obj).Age);
        }
 
        return 1;
    }
}

在Student类中实现了IComparable接口,在CompareTo方法中比较Student的Age属性,这一次再次编译运行,程序正常的输出了按照年龄排序的Student数组。

假如说我们要对Student的Score属性进行排序该怎么办呢? Student类实现的IComparable接口只能按照一种属性排序呀。

这个是很容易实现的.net的类库开发者早为我们准备了另一个接口IComparer<T>接口用来实现比较类型T的两个实例。如下StudentScoreComparer类实现了对Student按照Score属性比较的IComparer<Student>

1
2
3
4
5
6
7
public class StudentScoreComparer : IComparer<Student>
{
    public int Compare(Student x, Student y)
    {
        return x.Score.CompareTo(y.Score);
    }
}

现在我们可以使用下面代码对Student数组按照Score属性进行排序:

1
2
3
Console.WriteLine("----------按分数排序输出------------");
Array.Sort(students, new StudentScoreComparer());
Array.ForEach<Student>(students, (s) => Console.WriteLine(string.Format("{0}{1,2}岁了,他的分数是{2,3}", s.Name, s.Age, s.Score)));

不过一个简单的按照Score属性排序,再定义一个类是不是有点大题小作呀,有没有更好的办法呢?当然有. .net为我们准备了比较对象大小的委托Comparison<T>我们可以使用拉姆达表达式或者匿名委托直接排序,如下代码实现:

1
2
3
Console.WriteLine("----------按分数排序输出----------");
Array.Sort(students, (s1, s2) => s1.Score.CompareTo(s2.Score));
Array.ForEach<Student>(students, (s) => Console.WriteLine(string.Format("{0}{1,2}岁了,他的分数是{2,3}", s.Name, s.Age, s.Score)));

完整代码示例如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
 
namespace SortingInCSharp
{
    class Program
    {
        public class Student : IComparable
        {
            public int Age { getset; }
 
            public string Name { getset; }
 
            public int Score { getset; }
 
            /// <summary>
            /// 实现IComparable接口,用Age做比较
            /// </summary>
            /// <param name="obj">比较对象</param>
            /// <returns>比较结果</returns>
            public int CompareTo(object obj)
            {
                if (obj is Student)
                {
                    return Age.CompareTo(((Student)obj).Age);
                }
 
                return 1;
            }
        }
 
        static void Main(string[] args)
        {
            Student[] students = new Student[]{
                new Student(){Age = 10,Name="张三",Score=70},
                new Student(){Age = 12,Name="李四",Score=97},
                new Student(){Age = 11,Name="王五",Score=80},
                new Student(){Age = 9,Name="赵六",Score=66},
                new Student(){Age = 12,Name="司马",Score=90},
            };
 
            Console.WriteLine("--------------默认排序输出--------");
            Array.Sort(students);
            Array.ForEach<Student>(students, (s) => Console.WriteLine(string.Format("{0}{1,2}岁了,他的分数是{2,3}", s.Name, s.Age, s.Score)));
 
            Console.WriteLine("----------按分数排序输出------------");
            Array.Sort(students, new StudentScoreComparer());
            Array.ForEach<Student>(students, (s) => Console.WriteLine(string.Format("{0}{1,2}岁了,他的分数是{2,3}", s.Name, s.Age, s.Score)));
 
            Console.WriteLine("----------按分数排序输出----------");
            Array.Sort(students, (s1, s2) => s1.Score.CompareTo(s2.Score));
            Array.ForEach<Student>(students, (s) => Console.WriteLine(string.Format("{0}{1,2}岁了,他的分数是{2,3}", s.Name, s.Age, s.Score)));
 
 
            Console.Read();
        }
 
        public class StudentScoreComparer : IComparer<Student>
        {
            public int Compare(Student x, Student y)
            {
                return x.Score.CompareTo(y.Score);
            }
        }
    }
}

总结:

在C#中有三个关于比较对象大小的接口,分别是IComparable、IComparable<T>和IComparer<T>。 IComparable和IComparable<T>是类本身实现的在实例之间比较大小的行为定义。IComparer<T>是定义在被比较类之外的专门比较两个T类型对象大小的行为,另外还有一个用于比较的委托定义Comparison<T>可以让我们用拉姆达表达式或者匿名委托或方法更方便的排序。

【C#】基础之数组排序,对象大小比较(对比器)的更多相关文章

  1. C#基础之数组排序,对象大小比较

    从个小例子开始: 1 2 3 int[] intArray = new int[]{2,3,6,1,4,5}; Array.Sort(intArray); Array.ForEach<int&g ...

  2. C++类对象大小的计算

    (一)常规类大小计算 C++类对象计算需要考虑很多东西,如成员变量大小,内存对齐,是否有虚函数,是否有虚继承等.接下来,我将对此举例说明. 以下内存测试环境为Win7+VS2012,操作系统为32位 ...

  3. Java虚拟机14:Java对象大小、对象内存布局及锁状态变化

    一个对象占多少字节? 关于对象的大小,对于C/C++来说,都是有sizeof函数可以直接获取的,但是Java似乎没有这样的方法.不过还好,在JDK1.5之后引入了Instrumentation类,这个 ...

  4. Java虚拟机18:Java对象大小、对象内存布局及锁状态变化

    一个对象占多少字节? 关于对象的大小,对于C/C++来说,都是有sizeof函数可以直接获取的,但是Java似乎没有这样的方法.不过还好,在JDK1.5之后引入了Instrumentation类,这个 ...

  5. Java基础-IO流对象之序列化(ObjectOutputStream)与反序列化(ObjectInputStream)

    Java基础-IO流对象之序列化(ObjectOutputStream)与反序列化(ObjectInputStream) 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.对象的序 ...

  6. Java基础-IO流对象之转换流(InputStreamReader与OutoutStreamWriter)

    Java基础-IO流对象之转换流(InputStreamReader与OutoutStreamWriter) 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.转换流概述 我们之前 ...

  7. 两种计算Java对象大小的方法

    之前想研究一下unsafe类,碰巧在网上看到了这篇文章,觉得写得很好,就转载过来.原文出处是: http://blog.csdn.net/iter_zc/article/details/4182271 ...

  8. Java对象大小计算

    这篇说说如何计算Java对象大小的方法.之前在聊聊高并发(四)Java对象的表示模型和运行时内存表示 这篇中已经说了Java对象的内存表示模型是Oop-Klass模型. 普通对象的结构如下,按64位机 ...

  9. (转)JS获取当前对象大小以及屏幕分辨率等

    原文 JS获取当前对象大小以及屏幕分辨率等   <script type="text/javascript">function getInfo(){       var ...

随机推荐

  1. 按行读入xml文件,删除不需要的行 -Java

    删除挺麻烦的,这里其实只是把需要的行存到arraylist中再存到另一个文件中 import java.io.BufferedReader;import java.io.BufferedWriter; ...

  2. console调试命令

    一.显示信息的命令 <!DOCTYPE html> <html> <head> <title>常用console命令</title> < ...

  3. 对 block 内存管理的一些看法

    首先交代一下retain cycle ,和 产生retain cycle后我们应该怎么处理. 1.retain cycle在block中是极易产生,block就是一段可以灵活使用的代码,你可以把它当做 ...

  4. 基于MATLAB的滤波算法

    目前比较经典的图像去噪算法主要有以下三种: 均值滤波:也称线性滤波,主要思想为邻域平均法,即用几个像素灰度  的平均值来代替每个像素的灰度.有效抑制加性噪声,但容易引起图像模糊,  可以对其进行改进, ...

  5. SDUT OJ 2054 双向链表的实现 (结构体node指针+遍历 *【模板】)

    双向链表 Time Limit: 1000ms   Memory limit: 65536K  有疑问?点这里^_^ 题目描述 学会了单向链表,我们又多了一种解决问题的能力,单链表利用一个指针就能在内 ...

  6. vue 更改头像功能实现

     ——————– 如上图所示:需要完成的功能是点击更改头像,获取本地文件库,选择图片后将原始图片替换.这里我就直接用html文件引入vue来简单实现在这功能,代码如下: HTML: <div i ...

  7. 转:Oracle:删除表空间

    原文:http://space.itpub.net/40239/viewspace-365948 OMF和非OMF管理的数据文件在DROP TABLESPACE时是否会自动删除,做了测试: SQL&g ...

  8. 中文用户名的js检验正则

    原文:http://www.jb51.net/article/20719.htm 好多网站需要用中文用户名注册,下面的代码就是客户端检测.强烈建议后台也要控制一下. username1: " ...

  9. Unity5.6打包问题

    将unity切换到5.6版本后打Android包时,提示android sdk tools version低于compile version,于是更新了android-sdk(下载了Android-S ...

  10. OpenCV——PS滤镜算法之 Ellipsoid (凹陷)

    // define head function #ifndef PS_ALGORITHM_H_INCLUDED #define PS_ALGORITHM_H_INCLUDED #include < ...