一、int 和string 类型的的集合的排序

1 static void Main(string[] args) 2 { 3 //ArrayList list = new ArrayList() {1,8,3,992,888,33,77,38,2,34 };//数字 4 //ArrayList list = new ArrayList() {"Joney","Tindy","Bruce","Wesley","Candy","Alice","Tom"};//字符 5 ArrayList list = new ArrayList() {"张三","李四","王五","赵六","刘七","钱八"};//数字 6 Console.WriteLine("排序前:"); 7 for (int i = 0; i < list.Count; i++) 8 { 9 Console.Write(list[i]+" "); 10 } 11 Console.WriteLine(""); 12 13 //排序 14 list.Sort(); 15 list.Reverse(); 16 //排序后 17 Console.WriteLine("排序后:"); 18 for (int i = 0; i < list.Count; i++) 19 { 20 Console.Write(list[i]+" "); 21 } 22 23 Console.ReadKey(); 24 }
int 类型,是根据数字大小,降序排列。string类型是根据首字符的汉语拼音排序,这个都比较好理解。如果改成类的实例呢?

1 static void Main(string[] args) 2 { 3 //ArrayList list = new ArrayList() {1,8,3,992,888,33,77,38,2,34 };//数字 4 //ArrayList list = new ArrayList() {"Joney","Tindy","Bruce","Wesley","Candy","Alice","Tom"};//字符 5 //ArrayList list = new ArrayList() {"张三","李四","王五","赵六","刘七","钱八"};//数字 6 ArrayList list = new ArrayList() { 7 new Person() { Name="张三" }, 8 new Person() { Name="李四" }, 9 new Person() { Name="王五" }, 10 new Person() { Name="赵六" }, 11 new Person() { Name="刘七" }, 12 new Person() {Name="钱八" } 13 }; 14 Console.WriteLine("排序前:"); 15 for (int i = 0; i < list.Count; i++) 16 { 17 Console.Write(list[i]+" "); 18 } 19 Console.WriteLine(""); 20 21 //排序 22 list.Sort(); 23 list.Reverse(); 24 //排序后 25 Console.WriteLine("排序后:"); 26 for (int i = 0; i < list.Count; i++) 27 { 28 Console.Write(list[i]+" "); 29 } 30 31 Console.ReadKey(); 32 }
上述代码在list.sort()那报错了(无法比较的对象,至少有一个对象实现IComparable)。
这里可以这样理解:前面排序的时候,根据数值大小,字母顺序 排序,但是到了给对象排序的时候,编译器很迷茫,不知道根据什么排序,所以程序报错了,卡在了这里。打开详细信息,提示需要实现IComparable接口。我们把上面的代码改写下:

1 class Program 2 { 3 static void Main(string[] args) 4 { 5 //ArrayList list = new ArrayList() {1,8,3,992,888,33,77,38,2,34 };//数字 6 //ArrayList list = new ArrayList() {"Joney","Tindy","Bruce","Wesley","Candy","Alice","Tom"};//字符 7 //ArrayList list = new ArrayList() {"张三","李四","王五","赵六","刘七","钱八"};//数字 8 ArrayList list = new ArrayList() { 9 new Person() { Name="张三",Age=18 }, 10 new Person() { Name="李四" ,Age=48}, 11 new Person() { Name="王五",Age=14 }, 12 new Person() { Name="赵六" ,Age=33}, 13 new Person() { Name="刘七",Age=27 }, 14 new Person() {Name="钱八" ,Age=41} 15 }; 16 Console.WriteLine("排序前:"); 17 for (int i = 0; i < list.Count; i++) 18 { 19 Console.Write(((Person)list[i]).Name+" "); 20 } 21 Console.WriteLine(""); 22 23 //排序 24 list.Sort(); 25 list.Reverse(); 26 //排序后 27 Console.WriteLine("排序后:"); 28 for (int i = 0; i < list.Count; i++) 29 { 30 Console.Write(((Person)list[i]).Name + " "); 31 } 32 33 Console.ReadKey(); 34 } 35 } 36 37 public class Person:IComparable 38 { 39 public string Name { get; set; } 40 public int Age { get; set; } 41 public int CompareTo(object obj) 42 { 43 Person p=obj as Person; 44 if (p != null) 45 { 46 return p.Age - this.Age; 47 } 48 else 49 { 50 throw new InvalidOperationException("无效的操作"); 51 } 52 } 53 }
输出后的结果是根据年龄升序排列的:
排序前:
张三 李四 王五 赵六 刘七 钱八
排序后:
王五 张三 刘七 赵六 钱八 李四
其实我们看反编译后的代码,不管是int还是string,都实现了IComparable接口。也就是说,想调用ArrayList中sort()方法排序,集合中的元素都必须实现IComparable接口。
接下来,我们把程序写得灵活点。上面我们把排序的字段写死了,如果更换排序的依据,需要更改方法中的代码。我们能否不改类中方法中的代码,也能根据用户的想法排序呢?这需要我们写个排序的比较器。

1 class Program 2 { 3 static void Main(string[] args) 4 { 5 //ArrayList list = new ArrayList() {1,8,3,992,888,33,77,38,2,34 };//数字 6 //ArrayList list = new ArrayList() {"Joney","Tindy","Bruce","Wesley","Candy","Alice","Tom"};//字符 7 //ArrayList list = new ArrayList() {"张三","李四","王五","赵六","刘七","钱八"};//数字 8 ArrayList list = new ArrayList() { 9 new Person() { Name="张三",Age=18 }, 10 new Person() { Name="李四" ,Age=48}, 11 new Person() { Name="王五",Age=14 }, 12 new Person() { Name="赵六" ,Age=33}, 13 new Person() { Name="刘七",Age=27 }, 14 new Person() {Name="钱八" ,Age=41} 15 }; 16 Console.WriteLine("排序前:"); 17 for (int i = 0; i < list.Count; i++) 18 { 19 Console.Write(((Person)list[i]).Name+" "); 20 } 21 Console.WriteLine(""); 22 23 //排序 24 list.Sort(new SortPersonByName()); 25 //list.Reverse(); 26 //排序后 27 Console.WriteLine("排序后:"); 28 for (int i = 0; i < list.Count; i++) 29 { 30 Console.Write(((Person)list[i]).Name + " "); 31 } 32 33 Console.ReadKey(); 34 } 35 } 36 37 /// <summary> 38 /// 根据姓氏排序 39 /// </summary> 40 public class SortPersonByName : IComparer 41 { 42 public int Compare(object x, object y) 43 { 44 Person p1 = x as Person; 45 Person p2 = y as Person; 46 if (p1 != null && p2 != null) 47 { 48 return p1.Name.CompareTo(p2.Name); 49 } 50 else 51 { 52 throw new Exception("排序异常"); 53 } 54 } 55 } 56 57 /// <summary> 58 /// 根据年龄排序 59 /// </summary> 60 public class SortPersonByAge : IComparer 61 { 62 public int Compare(object x, object y) 63 { 64 Person p1 = x as Person; 65 Person p2 = y as Person; 66 if (p1!=null&&p2!=null) 67 { 68 return p1.Age - p2.Age; 69 } 70 else 71 { 72 throw new Exception("排序异常"); 73 } 74 } 75 }
如上代码,我们在调用list.sort()的时候传入自己编写的比较器,就可以个性化定制排序依据。需要强调的是,根据对象的Name排序的时候,由于字符串本身有compareto方法,可以直接调用。