Sort和OrderBy的定义比较
1、List.Sort()排序:
Sort并不是简单的快速排序,它对普通的快速排序进行了优化,它还结合了插入排序和堆排序。系统会根据你的数据形式和数据量自动选择合适的排序方法,这并不是说它每次排序只选择一种方法,它是在一次完整排序中不同的情况选用不同方法,比如给一个数据量较大的数组排序,开始采用快速排序,分段递归,分段之后每一段的数据量达到一个较小值后它就不继续往下递归,而是选择插入排序,如果递归的太深,他会选择堆排序。
说明:
a. 使用Sort排序时,有可能会打破数组列表的基本顺序。在数据相同的项具有不同含义时,不能使用Sort排序;
b. Array.Sort和List.Sort采用的是同一个排序方法。
2、Linq.Orderby()排序:使用快速排序,不会破坏数组列表的基本顺序。
快速排序是C.R.A.Hoare于1962年提出的一种划分交换排序。它采用了一种分治的策略,通常称其为分治法(Divide-and-ConquerMethod)。该方法的基本思想是:
1.先从数列中取出一个数作为基准数。
2.分区过程,将比这个数大的数全放到它的右边,小于或等于它的数全放到它的左边。3.再对左右区间重复第二步,直到各区间只有一个数。《菜鸟教程》
应用示例
对于纯Int或者double类型的List,可以直接使用List.Sort()或者List.Reverse()进行升序或降序排序操作。
对于非基本类型的排序,我们先做出下面的一个示例
先创建一个自定义类型
public class Student
{
public double Score { get; set; }
public string Name { get; set; }
public int Age { get; set; }
}
然后创建一个实例
List<Student> stuList = new List<Student>()
{
new Student(){Score = 90,Name="Tim",Age=29},
new Student(){Score = 98,Name="Tom",Age=28},
new Student(){Score = 98,Name="Tomi",Age=23},
new Student(){Score = 82,Name="Kyle",Age=27},
new Student(){Score = 76,Name="Tony",Age=26},
new Student(){Score = 96,Name="moly",Age=39},
new Student(){Score = 86,Name="Tkiy",Age=29},
new Student(){Score = 97,Name="Vina",Age=25},
new Student(){Score = 95,Name="Mike",Age=24},
new Student(){Score = 95,Name="Coki",Age=29},
};
一、使用OrderBy方法排序
我们先将StuList用Score排序,然后用Age排序 ,这里使用Lambda表达式
List<Student> list1 = stuList.OrderBy(t => t.Score).ThenBy(x=>x.Age).ToList();//升序
List<Student> list1 = stuList.OrderByDescending(t => t.Score).ThenByDescending(x=>x.Age).ToList();//降序
二、使用Sort方法排序
查看Sort的源码可以发现它有如下的几个重载:
public void Sort();
public void Sort(IComparer<T> comparer);
public void Sort(Comparison<T> comparison);
public void Sort(int index, int count, IComparer<T> comparer);
- 不带有任何参数的Sort方法----Sort();
- 带有比较器参数的Sort方法 ----Sort(IComparer)
- 带有比较代理方法参数的Sort方法----Sort(Comparison<(Of <(T>)>))
- 带有比较器参数,可以指定排序范围的Sort方法----Sort(Int32, Int32 IComparer(T))
1、实现IComparer接口
在自定义类型里实现IComparer接口,此处要注意:返回值,小于0代表x < y,等于0代表x=y,大于0代表x > y.
public class Student : IComparer<Student>
{
public double Score { get; set; }
public string Name { get; set; }
public int Age { get; set; }
public int Compare(Student x, Student y)
{
if (x.Score == y.Score && x.Age == y.Age)
{
return 0;
}
else
{
if (x.Score.CompareTo(y.Score) > 0)
{
return 1;
}
else if (x.Score == y.Score && x.Age > y.Age)
{
return 1;
}
else
{
return -1;
}
}
}
}
调用
IComparer<Student> comparer = new Student();
stuList.Sort(comparer);
2、实现IComparable接口
在自定义类型里实现IComparable接口,此处要注意:返回值,小于0代表x < y,等于0代表x=y,大于0代表x > y 只是与上面一个方法的调用形式不一样。
public class Student : IComparable<Student>
{
public double Score { get; set; }
public string Name { get; set; }
public int Age { get; set; }
public int CompareTo(Student other)
{
if (null == other)
{
return 1;
}
int re = this.Score.CompareTo(other.Score);
if (0 == re)
{
return this.Age.CompareTo(other.Age);
}
return re;
}
}
调用
stuList.Sort();
3、使用Comparison委托
查看Comparison的源码可以发现,Comparison委托的定义如下:
public delegate int Comparison<in T>(T x, T y);
使用委托,可以传递一个与委托签名相同的函数,可以使用匿名委托,还可以用Lambda表达式:
使用匿名委托调用:
stuList.Sort(delegate (Student x, Student y)
{
if (x.Score == y.Score && x.Age == y.Age)
{
return 0;
}
else
{
if (x.Score.CompareTo(y.Score) > 0)
{
return 1;
}
else if (x.Score == y.Score && x.Age > y.Age)
{
return 1;
}
else
{
return -1;
}
}
});
对于List的排序,也就是实现接口、使用委托,OrderBy方法,lambda表达式只是让形式更简单,并不能达到加快速度的效果。
结论:对于大数据量的数据排序,建议使用Sort()的扩展方法来实现,如果是小数据量,则直接使用OrderBy()方法更为简洁。