A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

本帖最后由 了无尘 于 2012-3-28 16:48 编辑

日常应用中,经常碰到这么样的问题,比如说,我有一个int数组需要排序,还有一个long数组进行排序,可能还有未知的对象数组需要排序,就好比基础题里边的给学生成绩排序那样,每次我们都要重新写一个代码去排序吗?这样的话重复代码有多少,更万恶的就是如果你根本不知道运行时会有怎么的对象数组需要进行什么排序,这样的代码怎么写?我想很多人都崩溃了,呵呵,其实this is so easy

那么总结下命题,对任意对象的成员变量,或者方法的返回值做为依据而对对象数组进行排序。

这里可以发现,如果需要实现这个功能吗,那么首先我们要在不知道对象的类型的情况下知道他的成员变量的值,或者是相关方法的返回值。

首先,我们先解决怎么获得任意对象的成员变量的值的问题
  1. class Cat
  2. {
  3.         public int age = 1;
  4. }
复制代码
对于这个Cat类的age变量,取得他的值可以通过映射方式来获得,学过映射都应该知道映射其实就是把整个类的所有成员给你映射成相关的对象。
  1.                 Cat cat = new Cat();
  2.                 System.out.println(cat.getClass().getField("age").get(cat));
复制代码
这样控制台就打印出了这个cat对象的age变量的值为1。
  1. class Cat
  2. {
  3.         private int age = 1;
  4.        
  5.         public Cat()
  6.         {
  7.                
  8.         }
  9.         public Cat(int age)
  10.         {
  11.                 this.age = age;
  12.         }
  13.         public int getAge()
  14.         {
  15.                 return age;
  16.         }
  17. }
复制代码
这样的私有成员,除非我们把访问权限改了,要不然会通过上边的字段方式是不能访问的,所以我们可以访问他的函数,拿返回值
  1. Cat cat = new Cat();
  2.                 System.out.println(cat.getClass().getMethod("getAge").invoke(cat));
复制代码
这里的invoke方法就是执行一次这个方法,如果有返回值就返回,void返回null。

但是到这呢,我们会发现一个奇怪的问题,这和我们想的不太一样,因为变量有可能其他的类型(这里暂时只说整数和浮点),难道我们还需要去逐一检测类型?其实最简单的办法就是在排序时,把他们全变成double,这样子,包括整数和浮点都可以进行对比了。
  1. (double)cat.getClass().getMethod("getAge").invoke(cat)
复制代码
这个代码是错误的,原因是强制转化失败,呵呵,还记得基本类型的包装类吗,parsexxx这个函数果断的是很好用的
  1. Double.parseDouble(cat.getClass().getMethod("getAge").invoke(cat).toString())
复制代码
现在准备工作做完了,我们可以开始写个简单的例子试试成果。
  1. Cat[] cats = {new Cat(100),new Cat(150),new Cat(50)};
  2.                 for (Cat cat : cats)
  3.                 {
  4.                         System.out.println(Double.parseDouble(cat.getClass().getMethod("getAge").invoke(cat).toString()));
  5.                 }
复制代码
100.0
150.0
50.0
输出木有问题,这里用的是调用函数来取值,如果是访问成员的话,用field那个方式。但是有些对象的成员是私有的,你只能用函数,所以,这两种方式我们都应该提供。
这里还有一个新东西,没发现的去撞墙,呵呵,就是吧,我们说的是任意对象对吧,那我们在来一个Wolf吧
  1. class Wolf
  2. {
  3.         public int age = 10;
  4.        
  5.         public Wolf()
  6.         {
  7.                
  8.         }
  9.         public Wolf(int age)
  10.         {
  11.                 this.age = age;
  12.         }
  13.         public int getAge()
  14.         {
  15.                 return age;
  16.         }
  17.        
  18.         public String toString()
  19.         {
  20.                 return ""+age;
  21.         }
  22. }

  23. class Cat
  24. {
  25.         private int age = 1;
  26.        
  27.         public Cat()
  28.         {
  29.                
  30.         }
  31.         public Cat(int age)
  32.         {
  33.                 this.age = age;
  34.         }
  35.         public int getAge()
  36.         {
  37.                 return age;
  38.         }
  39.        
  40.         public String toString()
  41.         {
  42.                 return ""+age;
  43.         }
  44. }


  45. Object[] objects = {new Wolf(100),new Cat(150),new Cat(50)};
  46.                 for (Object object : objects)
  47.                 {
  48.                         System.out.println(Double.parseDouble(object.getClass().getMethod("getAge").invoke(object).toString()));
  49.                 }
复制代码
到这呢,其实输出就知道了,我们发所有具有getAge方法的对象,我们全可以拿来排序。。。或者只要具有相同的可以访问的成员变量的对象也行,这个跟以前我们需要他们都继承一个超类来达到上朔遍历不太一样,我们这个更开放,更自由,但是这个猫和狼呢,确实还是要一个动物的超类,这样更好理解一些东西,这个在我另外一个帖子抽象和接口选择那里有说。

好了,到这,我想应该都看明白了,只需要在实现下排序就可以了,拿值的问题都已经解决,排序的话就照葫芦画瓢就行了,下边把完整的代码贴一下,bug肯定多,就是演示下反射的简单用途,当然这是最简单的用法。
  1. import java.lang.reflect.InvocationTargetException;



  2. class Wolf
  3. {
  4.         public int age = 10;
  5.        
  6.         public Wolf()
  7.         {
  8.                
  9.         }
  10.         public Wolf(int age)
  11.         {
  12.                 this.age = age;
  13.         }
  14.         public int getAge()
  15.         {
  16.                 return age;
  17.         }
  18.        
  19.         public String toString()
  20.         {
  21.                 return ""+age;
  22.         }
  23. }

  24. class Cat
  25. {
  26.         public int age = 1;
  27.        
  28.         public Cat()
  29.         {
  30.                
  31.         }
  32.         public Cat(int age)
  33.         {
  34.                 this.age = age;
  35.         }
  36.         public int getAge()
  37.         {
  38.                 return age;
  39.         }
  40.        
  41.         public String toString()
  42.         {
  43.                 return ""+age;
  44.         }
  45. }
  46. public class lll
  47. {
  48.         public static final boolean FROM_SMALL_TO_LARGE = true;
  49.         public static final boolean FROM_LARGE_TO_SMALL = false;
  50.         public static void main(String[] args) throws SecurityException, IllegalArgumentException, NoSuchFieldException, IllegalAccessException, NoSuchMethodException, InvocationTargetException
  51.         {
  52.                
  53.                 Object[] objects = {new Wolf(15), new Cat(20), new Wolf(), new Cat()};
  54.                 for (Object object : objects)
  55.                 {
  56.                         System.out.println(object.toString());
  57.                 }
  58.                 bubbleSort(objects, "getAge()", FROM_SMALL_TO_LARGE);
  59.                 System.out.println("===============================>");
  60.                 for (Object object : objects)
  61.                 {
  62.                         System.out.println(object.toString());
  63.                 }
  64.                 System.out.println("===============================>");
  65.                 bubbleSort(objects, "age", FROM_LARGE_TO_SMALL);
  66.                 for (Object object : objects)
  67.                 {
  68.                         System.out.println(object.toString());
  69.                 }
  70.         }
  71.        
  72.         public static void bubbleSort(Object[] src, String expression, boolean is) throws NumberFormatException, IllegalArgumentException, SecurityException, IllegalAccessException, NoSuchFieldException, InvocationTargetException, NoSuchMethodException
  73.         {
  74.                 int index = expression.indexOf("()");
  75.                 if(index != -1)
  76.                 {
  77.                         expression = expression.substring(0, index);
  78.                 }
  79.                 double a,b;
  80.                 for (int i = 0; i < src.length; ++i)
  81.                 {
  82.                         for (int j = 0; j < src.length - i - 1; ++j)
  83.                         {
  84.                                 if(index != -1)
  85.                                 {
  86.                                         a = Double.parseDouble(src[j].getClass().getMethod(expression).invoke(src[j]).toString());
  87.                                         b = Double.parseDouble(src[j+1].getClass().getMethod(expression).invoke(src[j+1]).toString());
  88.                                 }
  89.                                 else
  90.                                 {
  91.                                         a = Double.parseDouble(src[j].getClass().getField(expression).get(src[j]).toString());
  92.                                         b = Double.parseDouble(src[j+1].getClass().getField(expression).get(src[j+1]).toString());
  93.                                 }
  94.                                 if(is && a > b)
  95.                                 {
  96.                                         swap(src, j, j+1);
  97.                                 }
  98.                                 else if(!is && a < b)
  99.                                 {
  100.                                         swap(src, j, j+1);
  101.                                 }
  102.                         }
  103.                 }
  104.         }
  105.         public static void swap(Object[] data, int i, int j)
  106.         {
  107.         Object temp = data[i];
  108.         data[i] = data[j];
  109.         data[j] = temp;
  110.     }
  111. }
复制代码
  1. 15
  2. 20
  3. 10
  4. 1
  5. ===============================>
  6. 1
  7. 10
  8. 15
  9. 20
  10. ===============================>
  11. 20
  12. 15
  13. 10
  14. 1
复制代码
最后说点啥呢,其实在编程里,很多东西都是活的,死记硬背是行不通的,呵呵,祝大家早日挺进黑马
关于一些其他的规则,你也可以自己定义,只有想不到,没有做不到,呵呵

另外在说点题外的,这个代码写之前我没有学过反射,也没看过视频,我原来只知道有反射这个东西,有个大概的记忆,写这个的时候都是查api写的,呵呵,其实看我的代码没什么用处,谁都能写,但是在工作中,不是所有的工作都是你会的,如果是你不会的,还没有人教你,那怎么办?

6 个回复

倒序浏览
Arrays类可以实现对数组的排序,还可以把数组中的元素放到集合中进行排。

关于任意对象的成员变量,成员变量名也不知道,所以用你的方法恐怕也不行吧。

回复 使用道具 举报
王国华 发表于 2012-3-28 16:19
Arrays类可以实现对数组的排序,还可以把数组中的元素放到集合中进行排。

关于任意对象的成员变量,成员变 ...

排序,怎么排呢,肯定是有规律可循的,呵呵
回复 使用道具 举报
理解错你的意思了。。你是依据不同对象的相同属性进行排序,佩服
回复 使用道具 举报
{:soso_e179:}
先顶一下  在看
回复 使用道具 举报
本帖最后由 王国华 于 2012-3-28 16:56 编辑

想到一个思路,就是将得到的age属性值作为键,对应的对象作为值存入TreeMap(不用泛型) 中进行排序
再把对象取出到数组中
回复 使用道具 举报
王国华 发表于 2012-3-28 16:54
想到一个思路,就是将得到的age属性值作为键,对应的对象作为值存入TreeMap(不用泛型) 中进行排序
再把对象 ...

呵呵,这样的话不如直接用数组保存起来调用arrays.sort了,不过你这个遍历键也是想法,就是麻烦点
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马