`
Ivan0513
  • 浏览: 212590 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

比较器:基本类型单一通用比较器

阅读更多

当我们获得一个List后,如果希望它是按容器中,元素的某种属性排序的话,我们是可以通过

Collections.sort(myList, new my比较器())进行排序的。

但问题是,不同的属性要写不同的比较器,不同的类也要写比较器。

如果不希望重复劳动,就需要一个通用的比较器,所以写了以下代码。

 

我自己命名的:基本类型单一通用比较器 是指

(1)基本类型:元素的属性必须是:boolean,byte,char,int,long,float,double及他们的包装类 + String,Date,BigDecimal这几种类型

(2)所谓的单一(Single)是指:只比较类中的某一属性(不像SQL 的odrder by,后面可以跟n个,以后会扩展)

(3)通用(Universal)是指:任何类都可以用(希望如此)

 

废话少说,代码如下:

public final class BasicDataSingleUniversalComparator implements Comparator<Object> {

	private Class<?> c; //要比较的类
	private String fieldName; //根据类的哪个属性比较
	private Field field;
	private String filedTypeName; //属性类型名称
	//private Class<Object> attributeClass; //要比较的类的属性的类型
	private boolean isAsc; //比较结果是升序 or倒序, true:根据类属性自然比较结果的升序排列, false:根据类属性自然比较结果的倒序排列
	private int asc;

	private final static Map<String, String> compareMethods;
	
	static {
		compareMethods = new HashMap<String, String>();
		// * boolean,byte,char,int,long,float,double及他们的包装类 + String,Date这几种类型
		compareMethods.put("boolean", "compareBoolean");
		compareMethods.put("byte", "compareByte");
		compareMethods.put("char", "compareCharacter");
		compareMethods.put("character", "compareCharacter");
		compareMethods.put("int", "compareInteger");
		compareMethods.put("integer", "compareInteger");
		compareMethods.put("long", "compareLong");
		compareMethods.put("float", "compareFloat");
		compareMethods.put("double", "compareDouble");
		compareMethods.put("string", "compareString");
		compareMethods.put("date", "compareDate");
		compareMethods.put("bigdecimal", "compareBigDecimal");
	}
	
	//public SingleAttributeComparator(){}
	/**
	 * 构造函数
	 * @param c 要比较的类
	 * @param fieldName 类的某一属性名称
	 * @param isAsc 是根据此属性升序排列 or倒序排列 :true为升序,false为倒序
	 */
	public BasicDataSingleUniversalComparator(Class<?> c, String fieldName, boolean isAsc) 
		throws Exception {
		this.c = c;
		this.fieldName = fieldName;
		field = this.c.getDeclaredField(this.fieldName);
		filedTypeName = field.getType().getSimpleName();
		this.isAsc = isAsc;
		if(this.isAsc) {
			asc = 1;
		} else {
			asc = -1;
		}
	}
	
	@Override
	public int compare(Object o1, Object o2) {
		int result = 0;
//		String fieldType = field.getType().getSimpleName();
		try {
			field.setAccessible(true); //破坏了private,另外一种方案是:调用属性的get方法,但必须保证要有规范的get方法
			Object value1 = field.get(o1);
			Object value2 = field.get(o2);
			result = compareBasicData(value1, value2);
			
		} catch (Exception e) {
			e.printStackTrace();
		} 
		return result;
	}

	/**
	 * 认为null是最小的
	 * @param value1
	 * @param value2
	 * @return
	 * @throws NoSuchMethodException 
	 * @throws SecurityException 
	 */
	private int compareBasicData(Object value1, Object value2) throws Exception {
		int result = 0;
		if((value1 == null && value2 == null)) {
			result = 0;
		} else if(value1 == null) {
			result = -1*asc; //null是最小的,返回1*asc,如果是升序,则1*asc=1,否则1*asc=-1
		} else if(value2 == null) {
			result = 1*asc;
		} else if(value1.equals(value2)) {
			result = 0;
		} else {
			Method method = this.getClass().getDeclaredMethod(compareMethods.get(filedTypeName.toLowerCase()), Object.class, Object.class);
			result = (Integer)method.invoke(this, value1, value2);
		}
		return result*asc;
	}
	
	@SuppressWarnings("unused")
	private int compareBoolean(final Object value1, final Object value2) {
		Boolean v1 = (Boolean)value1;
		Boolean v2 = (Boolean)value2;
		return v1.compareTo(v2);
	}
	@SuppressWarnings("unused")
	private int compareByte(final Object value1, final Object value2) {
		Byte v1 = (Byte)value1;
		Byte v2 = (Byte)value2;
		return v1.compareTo(v2);
	}
	@SuppressWarnings("unused")
	private int compareCharacter(final Object value1, final Object value2) {
		Character v1 = (Character)value1;
		Character v2 = (Character)value2;
		return v1.compareTo(v2);
	}
	@SuppressWarnings("unused")
	private int compareInteger(final Object value1, final Object value2) {
		Integer v1 = (Integer)value1;
		Integer v2 = (Integer)value2;
		return v1.compareTo(v2);
	}
	@SuppressWarnings("unused")
	private int compareLong(final Object value1, final Object value2) {
		Long v1 = (Long)value1;
		Long v2 = (Long)value2;
		return v1.compareTo(v2);
	}
	@SuppressWarnings("unused")
	private int compareFloat(final Object value1, final Object value2) {
		Float v1 = (Float)value1;
		Float v2 = (Float)value2;
		return v1.compareTo(v2);
	}
	@SuppressWarnings("unused")
	private int compareDouble(final Object value1, final Object value2) {
		Double v1 = (Double)value1;
		Double v2 = (Double)value2;
		return v1.compareTo(v2);
	}
	@SuppressWarnings("unused")
	private int compareDate(final Object value1, final Object value2) {
		Date v1 = (Date)value1;
		Date v2 = (Date)value2;
		return v1.compareTo(v2);
	}
	@SuppressWarnings("unused")
	private int compareString(final Object value1, final Object value2) {
		String v1 = (String)value1;
		String v2 = (String)value2;
		return v1.compareTo(v2);
	}
	
	@SuppressWarnings("unused")
	private int compareBigDecimal(final Object value1, final Object value2) {
		BigDecimal v1 = (BigDecimal)value1;
		BigDecimal v2 = (BigDecimal)value2;
		return v1.compareTo(v2);
	}
}

 

使用方法如下:

例如我有一个Airport 机场类,里面有一个属性airportCode(机场三字码),

现在myList存放的是Airport元素列表,希望根据airportCode倒序排列(升序true,倒序false),那么

Collections.sort(myList, new BasicDataSingleUniversalComparator (Airport.class, "airportCode", false));

就搞定了。

 

 

 

分享到:
评论

相关推荐

    LM559比较器原版资料

    这表明LM559可能是一个特定型号,但相关资料和特性与LM339系列比较器是通用的,或者LM559可能是LM339系列中的一个型号,尽管在通用型号列表中未明确列出。 通过以上知识点,可以看出LM339系列比较器是非常适合需要...

    用单片机内置比较器设计高精度A/D变换器

    其基本原理是用单一的I/O端口,执行1位的数模转换,以比较器的输出作反馈,来维持Vout与Vin相等。该电路方案可以实现在MSP430F1121单片机上实现高精度A/D转换。 在该电路方案中,产生1位DAC的电路为一路通用I/O口、...

    通用网络爬虫综述.pdf

    集中式是指由单一主机执行爬取任务,这种架构中,由于单一主机的性能与计算资源的限制,比较适合执行任务量较小的爬取任务,如面向某一主题的网页抓取。而通用爬虫的任务量通常很大,集中式的架构不能满足效率和时间...

    SPWM专用控制芯片及微处理器应用比较

    #### 电动机控制专用微处理器:8XC196Mx系列 - **制造商**: Intel公司 - **系列型号**: 80C196MC/80C196MD/80C196MH等 - **类型**: 16位微处理器 - **应用领域**: 三相电动机变频调速控制 - **特点**: 高性能CMOS...

    CA0139AM.pdf

    这些设备由四个独立的单或双电源电压比较器组成,集成在单一的单晶硅基板上。它们能够处理包括接地在内的宽范围输入电压,并且由于低功耗特性,非常适合电池供电的应用场景。此外,它们还被设计为可以直接与TTL和...

    c和c++代码精粹.rar

    - 迭代器:遍历容器中的元素,执行各种操作。 - 预定义算法:如排序(sort)、查找(find)、交换(swap)等。 - 功能对象:如函数对象(functors)、比较函数对象、适配器等。 6. **输入/输出流**: - 文件流...

    新手入门:写Java程序的三十个基本规则

    - `static final`修饰的基本类型标识符全大写,表示它们是编译时常量。 - Java包名全小写,即使包含多个单词,如`com.example.myapp`。 2. **通用方法**: - 创建通用类时,应提供`equals()`, `hashCode()`, `...

    c++程序员面试宝典(含代码)

    - **函数对象(functors)**:自定义行为,如比较器、变换器等。 5. **异常处理** - **异常的抛出与捕获**:理解try、catch和throw关键字的使用。 - **异常安全**:编写能够正确处理异常的代码,保证资源的正确...

    TMS28027数据手册(中文).pdf

    10. 比较器: - 提供比较器模块,用于信号分析和转换。 11. 封装选项: - 提供38脚DA薄型小型外尺寸封装(TSSOP)和48脚PT薄型方形扁平封装(LQFP)。 12. 电源与功耗: - 设计用于低功耗应用,支持小引脚封装,...

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

    - **比较器**:如果TreeSet集合未传入比较器,则集合中的元素需实现Comparable接口,以便进行排序。 #### 题目16:数据模型分类 - **知识点**:本题考查数据模型的分类。 - **树形结构**:层次模型使用树形结构...

    C++培训课程资料1

    - 迭代器:理解迭代器的工作原理,如何遍历容器中的元素。 - 预算器(algorithms):如排序、查找、变换等常用算法。 - 函数对象(functors)和适配器:如比较函数、谓词、函数指针转换等。 8. **C++11及更高...

    c++培训课程详细学习笔记

    1. 变量与数据类型:C++支持基本数据类型(如int、float、char)以及构造数据类型(如数组、结构体)。理解变量声明、初始化和作用域规则至关重要。 2. 运算符:包括算术运算符、比较运算符、逻辑运算符、赋值运算符...

    Sort(ICompareable,ICompare)

    我们可以创建一个实现了`IComparer&lt;Student&gt;`的类,然后在排序时传递这个比较器: ```csharp public class StudentNameComparer : IComparer { public int Compare(Student x, Student y) { return x.Name....

    最新C++面试试题荟萃

    - **变量和数据类型**:理解基本数据类型(如int, float, double, char等),以及如何声明和初始化变量。 - **运算符**:熟悉各种运算符,如算术运算符、比较运算符、逻辑运算符、赋值运算符等。 - **控制结构**...

    诺信泰iDrive智能伺服驱动器与传统伺服的比较.pdf

    当将iDrive智能伺服驱动器与传统的通用伺服驱动器进行比较时,差异显而易见: 1. 通用伺服驱动器通常需要外部运动控制卡或PLC发送脉冲信号,容易发生丢失脉冲现象。而iDrive采用网络通信,提高了信号传递的可靠性。...

    Solaris动态跟踪指南(带书签)

    - **数据类型**:包括基本类型(整型、浮点型等)和复合类型(指针、数组等)。 - **算术运算符**:支持基本的数学运算。 - **关系运算符**:用于比较操作,如 `、`&gt;` 等。 - **逻辑运算符**:`&&`、`||` 和 `!`。 -...

Global site tag (gtag.js) - Google Analytics