`
jsx112
  • 浏览: 315912 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

利用java反射机制实现对象集合按任意指定字段排序

阅读更多

    近来由于项目的需要,准备实现对象集合的排序问题,了解一下互联网上的排序方式,都是先声明一个类实现Comparator接口,在compare方法中对某一个具体的属性进行处理,然后通过Collections的排序方法进行集合排序。

   这样做的确能实现对象集合按对象某个已知的属性进行排序,譬如我实现姓名的排序(假定此对象拥有name属性),那么我可以这么写:

              //实现一个内部类实现Comparator,并重写其compare方法
	static class NameComparator implements Comparator<Object> {
		
		/**
		 * 根据name的ASCII比较对象
		 */
		public int compare(Object o1, Object o2) {
			return (o1.getName()).compareTo(o2.getName());
		}
	}

	/**
	 * 对指定的集合按照name属性进行排序
	 * @param list
	 * @return
	 */
	public static List<Object> TransmitSort(List<Object> list) {
		NameComparator wt = new NameComparator();
		Collections.sort(list, wt);
		return list;
	}

 

   这样的确可以实现集合按name属性进行排序,那么如果系统希望按age年龄这个属性进行排序呢,我们是不是还要写个AgeComparator来实现Comparator并重写其compare方法呢,答案是肯定的。

   那将来系统需求发生变更,需要对其它属性进行类似的功能呢,我不得不为这排序的策略感到头疼,这无止境的实现并重写可不是一个明智的选择。不过在了解了Java反射的机制后,我突然有一种想法,能不能通过反射的手段在compare方法中做文章呢,这样,一旦我在实现Comparator的类中传递了某个属性,我就可以及时的获取相应的method并进行操作,这样可以吗?答案是肯定的,下面是我的代码实现:

package com.ysb.services.util;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

import com.ysb.services.entity.Resume;

/**
 * SortUtil.java verson 1.0 Aug 5, 2011
 * 
 * @author 贾世雄
 * 
 */
public class SortUtil {

	// 按任意属性进行排序
	static class AnyProperComparator implements Comparator<Object> {

		private String properName;// 根据此关键字属性排序

		private boolean flag;// 为true的时候是正序,为false的时候是倒序

		public AnyProperComparator(String properName, boolean flag) {
			super();
			this.properName = properName;
			this.flag = flag;
		}

		public void setProperName(String properName) {
			this.properName = properName;
		}

		public String getProperName() {
			return properName;
		}

		public boolean isFlag() {
			return flag;
		}

		public void setFlag(boolean flag) {
			this.flag = flag;
		}

		/**
		 * 实现Comparator的对比方法
		 * 
		 * @param r1
		 * @param r2
		 */
		@SuppressWarnings("unchecked")
		public int compare(Object r1, Object r2) {
			Class c = r1.getClass();
			double result = 0;
			try {
				Field field = c.getDeclaredField(properName);
				String classType = field.getType().getSimpleName();
				Method method = null;
				// 这里仅根据方法的返回值类型的名称来判定,比较方便
				if ("String".equals(classType)) {
					method = c.getMethod("get" + properName.substring(0, 1).toUpperCase() + properName.substring(1), new Class[] {});
					if (flag) {
						result = ((String) method.invoke(r1)).compareTo((String) method.invoke(r2));
					} else {
						result = ((String) method.invoke(r2)).compareTo((String) method.invoke(r1));
					}

				} else if ("Integer".equals(classType) || "int".equals(classType)) {
					method = c.getMethod("get" + properName.substring(0, 1).toUpperCase() + properName.substring(1), new Class[] {});
					if (flag) {
						result = ((Integer) method.invoke(r1)) - ((Integer) method.invoke(r2));
					} else {
						result = ((Integer) method.invoke(r2)) - ((Integer) method.invoke(r1));
					}
				} else if ("Double".equals(classType) || "double".equals(classType)) {
					method = c.getMethod("get" + properName.substring(0, 1).toUpperCase() + properName.substring(1), new Class[] {});
					if (flag) {
						result = ((Double) method.invoke(r1)) - ((Double) method.invoke(r2));
					} else {
						result = ((Double) method.invoke(r2)) - ((Double) method.invoke(r1));
					}
				} else if ("Float".equals(classType) || "float".equals(classType)) {
					method = c.getMethod("get" + properName.substring(0, 1).toUpperCase() + properName.substring(1), new Class[] {});
					if (flag) {
						result = ((Float) method.invoke(r1)) - ((Float) method.invoke(r2));
					} else {
						result = ((Float) method.invoke(r2)) - ((Float) method.invoke(r1));
					}
				} else {
					System.out.println("属性排序只支持数据类型和String类型,其它类型暂不支持。");
					result = -100;
				}
			} catch (SecurityException e) {
				e.printStackTrace();
			} catch (NoSuchFieldException e) {
				e.printStackTrace();
			} catch (NoSuchMethodException e) {
				e.printStackTrace();
			} catch (IllegalArgumentException e) {
				e.printStackTrace();
			} catch (IllegalAccessException e) {
				e.printStackTrace();
			} catch (InvocationTargetException e) {
				e.printStackTrace();
			}

			// 确定返回值
			if (result > 0) {
				return 1;
			} else if (result < 0) {
				return -1;
			}
			return 0;
		}

	}

	/**
	 * 按任意给定的字段进行排序,升序或降序由flag决定
	 * 
	 * @param list
	 * @param properName
	 * @param flag
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public static List<Resume> anyProperSort(List<Resume> list, String properName, boolean flag) {
		AnyProperComparator comparator = new AnyProperComparator(properName, flag);
		Collections.sort(list, comparator);
		return list;
	}

}

  

   这样一来,我想对某个集合排序,只需要调用SortUtil的方法anyProperSort即可,这样就可以大大的提高系统的扩展性,将来不用再为用户需求的变更而头疼了。

    不过需要注意的是反射一般比直接写性能要降低大约一倍,所以请读者慎重。

分享到:
评论

相关推荐

    List数据字段排序不关注数据库,直接排序

    在 Java 中,我们可以利用 `Collections.sort()` 方法结合自定义的 `Comparator` 来实现对 List 集合的排序。具体做法是创建一个实现了 `Comparator` 接口的类,并在 `compare()` 方法中定义具体的排序逻辑。这里的...

    Java面经.适用于校招

    - Java反射机制允许程序在运行时访问和操作类、接口、字段和方法等对象。 1.12 JDK、NDK、JRE、JNI - JDK(Java Development Kit)是用于开发Java程序的工具包。 - NDK(Native Development Kit)允许开发者用C或...

    Java软件开发实战 Java基础与案例开发详解 10-9 练习题 共5页.pdf

    #### 15.2 使用Java反射机制 通过反射,可以在运行时获取类的构造函数、方法、字段等信息。 #### 15.3 反射与动态代理 动态代理利用反射生成代理对象,可以用来增强或扩展对象的功能。 ### 十四、Java标注 ####...

    Java5.0中方帮助文档

    Java 5.0的内省机制提供了获取和修改对象、类、接口等元数据的能力,如通过反射访问私有方法和字段。 12. **NIO.2(New I/O 2)** 虽然NIO.2是在Java 7中引入的,但它是对Java 5.0 NIO的扩展,增加了文件系统操作...

    java常用API举例

    8. **反射机制**:Java反射允许程序在运行时检查类、接口、字段和方法的信息,并能动态创建对象和调用方法。例如: ```java Class&lt;?&gt; clazz = Class.forName("java.util.ArrayList"); Object instance = clazz.new...

    Java基础教程.md.pdf

    ##### 11.3 Java反射机制 - 反射允许程序在运行时获取类的信息并操作对象。 #### 12. 输入/输出(IO) ##### 12.1 File类 - 文件和目录的创建、删除等操作。 ##### 12.2 了解Java IO流 - 输入流:从源读取数据。 ...

    良葛格Java JDK 5.0学习笔记

    以及`Collections.sort()`方法,实现了集合的排序。 5. **变量枚举(Autoboxing/Unboxing)** 自动装箱和拆箱简化了基本类型与包装类之间的转换。例如,int和Integer可以自动相互转换,使得代码更加流畅。 6. **...

    Java api 文档

    7. **反射机制**: - `Class`类:代表运行时的类信息,可以通过`Class.forName()`获取。 - `Method`、`Constructor`和`Field`:分别表示类的方法、构造器和字段。 - `newInstance()`和`invoke()`:动态创建对象和...

    SimpleJava.pdf

    - **Comparator接口**:提供了外部比较器,允许按任意标准对对象进行排序。 - **使用场景**:根据实际需求选择合适的排序策略。 #### 13. Java中的equals()与hashCode()合同 - **equals()方法**:定义了两个对象...

    整理了一个关于网上java问与答的一个手册

    1. 反射API:Class类、Constructor类、Method类、Field类,用于运行时动态获取类信息,创建对象,调用方法,访问字段。 2. 动态代理:通过Proxy类和InvocationHandler接口实现,用于创建动态代理对象,增强功能或...

    java函数速查

    6. **反射机制** - `Class`类:获取类的信息,如类名、构造器、方法、字段等。 - `newInstance()`:动态创建对象。 - `getMethod()`和`invoke()`:动态调用方法。 7. **泛型** - 泛型用于定义类型安全的容器,...

    传智播客视频JavaSE学习笔记

    ### Java反射机制 #### 一、获取Class类的实例 反射机制允许在运行时动态获取类的信息,包括类名、构造函数、成员变量、方法等。 #### 二、创建对象 通过反射可以调用私有构造函数或默认构造函数创建对象,打破...

    java 编程常用英语单词 解释

    - **用途**:Java使用异常处理机制来处理运行时错误,如除零错误或文件未找到等。 #### Entry (条目) - **定义**:条目通常指数据结构中的单个元素或记录。 - **用途**:在集合类如HashMap中,每个键值对被视为一个...

    Java经典面试

    - `java.util.concurrent.locks.Lock`接口提供了更灵活的锁定机制,可以实现非阻塞等待、定时等待等功能。 #### 30. Java源文件的命名规则 - Java源文件应该以该文件中的公共类(public class)的名字命名,并且...

    java基础知识

    - 集合排序:Collections.sort()、TreeSet/TreeMap自然排序、Comparator比较器。 - 集合遍历:for-each循环、Iterator迭代器。 4. **学生信息管理系统实现**: - 学生信息类设计。 - 使用集合存储学生信息。 -...

    实验项目D、Java应用专题编程

    同时,给出了设计`MyStudent`类及其排序实现,展示了如何实现自定义比较器,通过`Collections.sort()`方法对`ArrayList`进行排序。 通过这个实验项目,学生将深化对Java语言的理解,提升实际编程能力,为后续的Java...

    中级程序员必备面试题.txt

    - **观察者模式**:实现对象间的解耦通信。 - **策略模式**:封装算法并使其可互换。 #### 设计模式名称 如果设计一个新的设计模式,可以命名为“智能代理模式”,用于智能地代理复杂操作。 #### 代码重构 - **...

    2021-2022计算机二级等级考试试题及答案No.19361.docx

    - **知识点解析**:Java和其他许多编程语言提供了集合框架,用于存储任意对象的类。这些类包括List(列表)、Set(集合)、Map(映射)等。集合框架提供了一种灵活的方式来管理和操作对象集合。所以,正确答案是**...

    unity面试题

    - **C#**: 由微软开发,结合了C++和Java的优点,面向对象,具有垃圾回收机制,主要用于Windows平台下的应用程序和游戏开发(尤其是Unity)。 - **个人熟悉度**: C#(适合Unity开发者)。 #### 3. 面向对象的特点 - ...

Global site tag (gtag.js) - Google Analytics