`
言日星极
  • 浏览: 23832 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

使用二分法查找java对象

阅读更多
        在J2EE Web项目开发中,Excel导入导出批量处理数据是比较常见的。在Excel导入时涉及到业务逻辑之类的校验。譬如说:导入的数据是否存在于数据库中,否做添加数据操作,是则作更新操作,大部分系统不只是单纯的更新数据,根据某些业务规则来确认是否更新数据,需要取到要更新的数据。而这个时候如果要遍历导入的数据集合,去数据库查询并取到与之相关的持久化数据,最终根据相关业务逻辑进行再一步操作。当然了像这种方式,如果要导入的数据有两三千条,那岂不是最少也要查询两三千次数据库?如果还有其他业务也需要查询数据库那么与数据库的交互就更频繁了,所以这种做法一般情况下不是太合理的,我们在实际开发中应该尽可能的减少和数据库的交互,以达到性能要求。
        我们可以从数据库中查询出相应的要更新的数据集合,这里我们叫它持久化数据集合,如果说要查找出与导入的数据集合中相应的数据,使用双重循环也是不错的选择。先循环导入的数据集合,然后拿当前遍历到的数据再来一个循环去持久化数据集合中查找对应的对象。但是一般建议不这样做,使用二分法(折半查找)替代双重循环要好的多。下面一个小demo演示了如何使用二分法在集合中查找相应的对象。

public class User implements Comparable<User>, Serializable{	
	private static final long serialVersionUID = -5410921420480739669L;
	private String name;				// 姓名
	private String nationalIdentifier;	// 身份证号码
	/**
	 * 实现Comparable接口的compareTo方法,该方法表示传入的对象与当前对象谁大谁小
	 * 传入的参数对象u的属性nationalIdentifier大于当前对象的natioanlIdentifier返回正数
	 * 否则返回负数,相等返回0(有兴趣的朋友可以查看String类的源码)
	 * 使用二分法在集合中查询某个元素的前提是该集合已经排序好了,如果要查找的元素是自定义类,则必须实现Comparable接口并实现compareTo接口
	 */
	@Override
	public int compareTo(User u) {
		if(u != null)
			// 调用了String类的compareTo方法
			return this.nationalIdentifier.compareTo(u.nationalIdentifier);
		return -1;
	}
	/**
	 * 重写Object类的equals方法
	 * 在这里两个User对象的姓名和身份证号码相等表示这两个User对象相等
	 */
	@Override
	public boolean equals(Object obj){
		User u = (User) obj;
		if(
			this.name.equals(u.name) 
				&& 
			this.nationalIdentifier.equals(u.nationalIdentifier)
			) {
			return Boolean.TRUE;
		}
		return Boolean.FALSE;
	}
	public User(String _name, String _nationalIdentifier){
		this.name = _name;
		this.nationalIdentifier = _nationalIdentifier;
	}
	// ... 其他代码
}


public class Application{
	
	public static void main(String[] args) {
		// 假设这里的iList是要导入的Excel数据集合 iList = import list
		List<User> iList = new ArrayList<User>(2);
		iList.add(new User("学点啥小许", "www.xuediansha.com/city.php?ename=shenzhen"));
		iList.add(new User("学点啥小周", "www.xuediansha.com/city.php?ename=guangzhou"));
		// 这里假设pList是从数据库中查询的持久化集合 pList = persistent list
		List<User> pList = new ArrayList<User>(6);
		pList.add(new User("学点啥老武", "www.xuediansha.com/city.php?ename=xian"));
		pList.add(new User("学点啥老周", "www.xuediansha.com/city.php?ename=beijing"));
		pList.add(new User("学点啥老许", "www.xuediansha.com/city.php?ename=shanghai"));
		pList.add(new User("学点啥小许", "www.xuediansha.com/city.php?ename=shenzhen"));
		// 在使用二分法在集合中查找某个元素需要将该集合进行排序,使用Collections工具类的sort方法即可
		Collections.sort(pList);
		// cUser = current user
		User cUser;
		// eUser = each User
		for(User eUser : iList) {
			cUser = binarySearch(pList, eUser);
			if(cUser != null) {
				System.out.println(cUser.getName());
				// ... 其他操作
			}
		}
	}
	/**
	 * 使用二分法在list集合中查找user对象
	 * @param list 传入的持久化数据集合
	 * @param user 要查询的对象
	 * @return
	 */
	public static User binarySearch(List<User> list, User user) {
		// curPos = current position
		int curPos;
		// startPos = start position
		int startPos = 0;
		// endPos = end position
		int endPos = list.size() - 1;
		// cUser = current user
		User cUser;
		int counts = 0;
		while(true) {
			// curPos = current position
			curPos = (startPos + endPos) / 2;
			cUser = list.get(curPos);
			if(user.equals(cUser)) {
				System.out.printf("查找了%d次\n", counts);
				return cUser;
			} else if (endPos < startPos) {
				return (cUser = null);
			} else {
				if(user.compareTo(cUser) > 0) {
					startPos = curPos + 1;
				} else {
					endPos = curPos - 1;
				}
			}
			counts++;
		}
	}
}


当然了,执行这样的批量更新操作,在将持久化数据查询出来的同时最好锁定这些数据,至于使用何种锁机制,根据不同系统业务来做决定(悲观锁/乐观锁)。
分享到:
评论

相关推荐

    21天学会Java之(Java SE第八篇):数组、冒泡排序法、二分法查找

    数组 数组的定义 数组是相同类型数据的有序集合,数组描述的是相同类型...数组本身就是对象,Java中对象是在堆中的,因此数组无论保存原始类型还是其他对象类型,数组对象本身是在堆中存储的。 数组声明 在声明数组变量

    java算法——插补查找法

    插补查找法 * 其原理与二分法查找是相同的,搜寻的对象大于500时, * 比二分法查找速度快 * (K-K1)/(Ku-K1)=(m-1)/(u-1)

    Java程序设计基础:一维数组应用查找线性查找).pptx

    二分法查找 数组的查找——线性查找 也称顺序查找法,基本思想: 11 22 43 90 4 90 56 49 -10 3 0 1 2 3 4 5 6 7 8 9 将要查找的对象(关键字key)与数组中每个元素逐一比较,如果某一元素值与关键词key相等,则表示...

    JAVA泛型简单排序实例

    JAVA泛型源代码实现以下功能:返回数组元素的最大值/最小值下标;判断数组元素是否按升序排列;T对象数组排序;二分法查找key元素;

    java常用工具类的使用

    该类的大部分构造器和方法都已经过时,但是该类使用非常方便,因此目前使用还很普遍,该类的另一个主要功能是,在数据库操作中,它允许将毫秒值表示为SQL DATE值,是数据库操作中java.sql.Date的父类。关于数据库...

    JAVA基础课程讲义

    JAVA对象的序列化和反序列化 161 为什么需要序列化和反序列化 161 对象的序列化主要有两种用途 161 序列化涉及的类和接口 162 序列化/反序列化的步骤和实例 162 综合的序列化和反序列化练习 163 JAVA.IO包相关流对象...

    java内部学习笔记.docx

    2.13二分法查找 13 2.14 Java系统API方法调用 14 2.15二进制基础 14 2.16 Java基础其他注意事项 14 面向对象 16 3.1类 16 3.2对象 16 3.3包 16 3.4方法及其调用 17 3.5引用 17 3.6访问控制(封装) 17 3.7构造器 17 ...

    javascript 二分法(数组array)

    在Javascript中,我们可以通过prototype关键字为对象添加新的属性或者是方法,下面是一个为Array对象添加二分法查找功能的方法: 代码如下: Array.prototype.binarySearch = function(obj) { var value = 0;...

    Java笔试题大汇总

    解析:二分法查找只适用于顺序存储的有序表。在此所说的有序表是指线性表中的元素按值非递减排列(即从小到大,但允许相邻元素值相等)。 2 在软件设计中,不属于过程设计工具的是__D____。 A、PDL(过程设计语言...

    Java实验报告(5).doc

    随机生成100个0到200的整数,用折半查找法(二分法)查找50是第几个数, 并输出查找过程(即和什么数进行了比较)。 (折半查找是在已经排序的数据中做的查找,所以先要排序) 2.显示任意一个月份的日历(&gt;1900)...

    Algorithms-and-data-structures---Java:自己根据书C语言版算法数据结构和一些资料,用Java实现其中经典的语法和算法结构

    根据书C语言版算法数据结构和一些资料,使用面向对象思想和Java语言实现其中经典的语法和算法结构。 按目录分别实现: 01 数组、升序、二分法查找 02 简单排序:冒泡排序、选择排序、插入排序 03 栈、队列、循环队列...

Global site tag (gtag.js) - Google Analytics