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. 20170223 遇到自建表里面相同key值数据不唯一

     我怎么发现这个表里 key值相同数据不唯一, 这两条看起来是完全相同的, 其实排序不能能合并已经说明问题.

  2. QT下的QThread学习(一)

    参考文档如下: http://blog.csdn.net/styyzxjq2009/article/details/8204506 上面这篇文章的开头也也出了另外两篇文章,一并看看,可以看到他的解决思 ...

  3. POJ3660 Cow Contest —— Floyd 传递闭包

    题目链接:http://poj.org/problem?id=3660 Cow Contest Time Limit: 1000MS   Memory Limit: 65536K Total Subm ...

  4. linux初级学习笔记十:linux grep及正则表达式!(视频序号:04_4)

    本节学习的命令:grep 本节学习的技能: grep对文本的匹配 正则表达式的使用 知识点十:grep及正则表达式(4_4) grep,egrep,fgrep: grep: 根据模式搜索文本,并将符合 ...

  5. Silverlight中使用MVVM(1)

    Silverlight中使用MVVM(1)   Silverlight中使用MVVM(1)--基础 Silverlight中使用MVVM(2)—提高 Silverlight中使用MVVM(3)—进阶 ...

  6. .NETFramework:HttpContext

    ylbtech-.NETFramework:HttpContext 1.返回顶部 1. #region 程序集 System.Web, Version=4.0.0.0, Culture=neutral ...

  7. git只clone仓库中指定子目录

    基于sparse clone变通方法 [root@vm_test backup]# mkdir devops[root@vm_test backup]# cd devops/[root@vm_test ...

  8. CodeForces 1103D. Professional layer

    题目简述:给定$1 \leq n \leq 10^6$个正整数$1 \leq a_i \leq 10^{12}$,修改第$i$个正整数$a_i$的花费为$1 \leq e_i \leq 10^9$,以 ...

  9. E20180423-hm

    disclosure  n. (发明等的) 公开; 泄露,揭露; 开诚布公的话; 被公开的事情,被披露的秘闻; alignment n. 结盟; 队列,排成直线; 校直,调整; [工] 准线; ali ...

  10. (水题)洛谷 - P1478 - 陶陶摘苹果(升级版)

    https://www.luogu.org/problemnew/show/P1478 没啥好说的…… 居然还漏写一个等于号WA了一发. #include<bits/stdc++.h> u ...