需求:
同一页面显示的内容需要到2个不同的数据库a,b中查询,a的结果中的id作为条件再到b中查询。
如a的结果数据量大,需要分次到b中查询。
JDK:1.6
持久层框架:ibatis2.0
要注意的细节:
1.循环次数
2.内存占用
public PageResult queryForPageListNew(int pageSize, int pageNum,AForm queryForm)
{
// 初始化循环次数
int i = 0;
// 初始化n
int n = 200;
// 获得a表单
PageResult pr = aDAO.queryForPageResult(queryForm
.getParams(), pageSize, pageNum, A.class);
List<A> aList = pr.getResultList();
// 初始化size
int size = aList.size();
// 创建临时数组,用于存放a表单中的id
List<Long> temp = new ArrayList<Long>();
// 初始化hashmap,size*2避免hashmap resize()
Map<Long, Long> countMap = new HashMap<Long, Long>(size*2);
for (A a : aList)
{
i++;
temp.add(a.getId());
// 每n条数据查询一次数据库
if (((i + n) % n == 0 && i < size)||(i==size))
{
// 由于使用某种特殊框架自动生成DAOImpl,目前只能返回List
List<Map<String, Long>> countMapList = bDAO
.queryCountByOwnerForList(temp);
// 将查询结果放入countMap中
for (Map<String, Long> map : countMapList)
{
Long id = map.get("owner");
Long count = map.get("count");
countMap.put(id, count);
}
temp.clear();
}
}
temp = null;
for (A a : aList)
{
a.setCount(countMap.get(a.getId()));
}
countMap.clear();
countMap = null;
return pr;
}
b的ibatis SqlMap:
<select id="queryCountByOwnerForList" resultMap="resultMap.B" parameterClass="List">
select
t1.owner,
count(t1.owner) as count
from t_b t1
where
(
t1.status= 4
or t1.status=5
or t1.status=6
)
and t1.owner in
<iterate open= "(" close = ")" conjunction = ",">
#[]#
</iterate>
group by t1.owner
</select>
HashMap countMap 使用说明:
两次的查询结果,需要比对id,进行组合。2次查询的结果集均未List,如直接组合,需要做for循环的嵌套,比对方式如下:
for(A a: aList){
for(B b: countMapList){
if(a.id==b.id)
{
组合...
}
}
}
这样就要循环n的平方次,才能组合查询结果,使用HashMap只需要循环2n次
这里假定使用HashMap存取结果比List嵌套循环快(没经过测试)
改进思考:
1.hashmap初始化的值应为
大于 (int)(size/0.75)+1 且最小的2的n次方
参见:http://www.iteye.com/topic/539465
2.不知道ibatis是否支持参数为List<Object>,并获得Object的属性。如果可以,能否省掉temp?
代码初评:
1.int n = 1000;
常量应该设置为fanal static
2.int size = aList.size();
可以直接用aList.size(),没有必要再定义一个变量
3.List<Long> temp = new ArrayList<Long>();
长度也可以初始化
4.if (((i + n) % n == 0 && i < size)||(i==size))
太复杂,不容易看懂,尽量用面对对象的思想,而且i<size的条件也是多余的
5.没有考虑第一次查询aList为空的情况,程序仍在继续往下执行
初评过后的代码:
private final static int SELECT_IN_NUMBER=200;
public PageResult queryForPageListNew(int pageSize, int pageNum,
CorpClaimSetQueryForm queryForm)
{
// 获得a查询分页表单
PageResult pr = aDAO.queryForPageResult(queryForm
.getParams(), pageSize, pageNum, A.class);
List<A> aList = pr.getResultList();
// 如果cssList查询结果为空直接返回pr
if (aList.size() <= 0)
{
return pr;
}
// 创建临时数组,用于存放a表单中的id
List<Long> temp = new ArrayList<Long>(SELECT_IN_NUMBER);
// 初始化hashmap,size*2避免hashmap resize()
Map<Long, Long> countMap = new HashMap<Long, Long>(aList.size() * 2);
for (A a : aList)
{
temp.add(a.getId());
// 每n条数据查询一次数据库
if (temp.size() == SELECT_IN_NUMBER)
{
List<Map<String, Long>> countMapList = bDAO
.queryCountByOwnerForList(temp);
// 将查询结果放入countMap中
for (Map<String, Long> map : countMapList)
{
Long id = map.get("owner");
Long count = map.get("count");
countMap.put(id, count);
}
//每查询1次,清空一次temp
temp.clear();
}
}
//对temp中余留的数据进行查询
if (!temp.isEmpty())
{
List<Map<String, Long>> countMapList = bDAO
.queryCountByOwnerForList(temp);
for (Map<String, Long> map : countMapList)
{
Long id = map.get("owner");
Long count = map.get("count");
countMap.put(id, count);
}
temp.clear();
temp = null;
}
//将统计结果加入到原有的查询结果中
for (A a : aList)
{
a.setCount(countMap.get(a.getId()));
}
countMap.clear();
countMap = null;
return pr;
}
再次评审:
1.集合调用clear()之后,不需要再设置为null(方法调用完后,内存会自动释放,这些操作都没必要?)
2.一段代码中用到相同的代码2次,这段相同的代码应该提炼出来,自成一个方法
最终代码:
private final static int SELECT_IN_NUMBER = 200;
/**
* 分页查询 在原有的基础上增加数量统计,并可进行批量统计,每n条统计一次。
* @param pageSize
* @param pageNum
* @param queryForm
* @return PageResult
*/
@SuppressWarnings("unchecked")
@Override
public PageResult queryForPageListNew(int pageSize, int pageNum,
CorpClaimSetQueryForm queryForm)
{
// 获得a查询分页表单
PageResult pr = aDAO.queryForPageResult(queryForm
.getParams(), pageSize, pageNum,A.class);
List<A> aList = pr.getResultList();
// 如果aList查询结果为空直接返回pr
if (aList.size() <= 0)
{
return pr;
}
// 创建临时数组,用于存放a中的id
List<Long> temp = new ArrayList<Long>(SELECT_IN_NUMBER);
// 初始化hashmap,size*2避免hashmap resize()
Map<Long, Long> countMap = new HashMap<Long, Long>(aList.size() * 2);
for (A a : aList)
{
temp.add(a.getId());
// 每n条数据查询一次数据库
if (temp.size() == SELECT_IN_NUMBER)
{
queryAndWarpCountMap(temp, countMap);
}
}
//对temp中余留的数据进行查询
if (!temp.isEmpty())
{
queryAndWarpCountMap(temp, countMap);
}
//将统计结果加入到原有的查询结果中
for (A a : aList)
{
a.setCount(countMap.get(a.getId()));
}
return pr;
}
/**
* 根据临时ID集合,查询统计数据,并且包装到统计map中。
* 最后清空临时ID集合
* @param temp
* @param countMap
*/
private void queryAndWarpCountMap(List<Long> temp, Map<Long, Long> countMap) {
List<Map<String, Long>> countMapList = bDAO
.queryCountByOwnerForList(temp);
for (Map<String, Long> map : countMapList)
{
Long id = map.get("owner");
Long count = map.get("count");
countMap.put(id, count);
}
//每查询1次,清空一次temp
temp.clear();
}
相关推荐
为了优化处理效率或满足特定需求,我们可能会需要将这个大数组按照某个倍数拆分成多个小数组。这个问题的解决方案在PHP中可以通过原生函数实现,无需额外依赖库。下面我们将详细讨论如何实现这一功能,并提供相关的...
大数相乘的基本思路是将每个大数拆分成数组中的每一位,然后按照传统的笔算乘法方法进行计算。下面我们将详细探讨这个过程: 1. **大数表示**:由于C语言没有内置的大数类型,我们需要使用数组来模拟大数。每个元素...
大数的乘法相对复杂一些,常见的算法有Karatsuba算法和Toom–Cook算法,这里我们可能采用了更基础的“学校乘法”方法,也就是将一个大数拆分为多个位,然后分别与另一个大数相乘,再将结果相加并适当调整位数。...
大数乘法可以采用分治的思想,将一个大数拆分为多个小部分,分别计算后再合并结果。另一种常见的方法是采用类似小学乘法的方式,即逐位相乘并累加。例如,在计算`45 * 12`时,可以先计算`5 * 12`得到`60`,再计算`4 ...
总之,这个项目提供了大数阶乘算法的源代码实现,对于理解和学习如何处理大整数的计算以及优化算法性能具有很高的价值。通过研究这些源代码,开发者可以深入理解大数处理的原理,并将其应用到其他需要处理大数的场景...
- **分段处理**:为了避免一次性处理整个大数,可以将每个数分成多个较小的段进行计算,然后再合并结果。这种方法可以减少内存占用并提高计算效率。 - **Karatsuba算法**:对于中等大小的数字,可以采用Karatsuba...
11. **分步替换**:对于可以拆分的替换操作,如字符替换,可以逐个替换,避免一次性处理数组。 12. **抑制错误报告**:使用@抑制错误会降低脚本运行速度,应尽量避免使用,而是通过良好的错误处理机制。 13. **...
在源码实现上,我们通常会用到数据结构如数组或链表来存储大数,因为普通的整数类型无法容纳大数。例如,可以定义一个大数类,包含一个数组来存储每一位,并提供加法、减法、乘法等基本操作。对于乘法操作,根据选择...
在数组拆分问题中,`array_chunk()`函数尤其重要,它可以将大数组拆分成多个小数组,每个小数组的元素数量由用户指定。 二、LeetCode数组拆分题目 1. **数组拆分I (Split Array into Consecutive Subsequences)**:...
Long Multiplication类似于手算乘法,将两个大数拆分成多位,然后进行逐位的乘法和累加。Karatsuba算法是一种分治策略,可以减少计算量。 5. **除法**:大数除法相对复杂,可以采用类似手算的长除法,或者使用更...
- Karatsuba算法:适用于较大的数,将大数拆分为较小的部分,然后通过递归公式进行计算,降低了计算复杂度。 - Toom-Cook算法:进一步扩展了Karatsuba算法,用于更多部分的分解。 5. **除法运算**: - 长除法:...
在编程领域,大数相乘是一项重要的计算任务,特别是在处理超过普通整型变量范围的数值时。本项目“大数相乘—操作(VC)”是使用Microsoft Visual Studio 2005(简称VC 2005)进行开发的一个控制台程序,专门针对大数...
在编程领域,大数的阶乘是一个挑战性的计算任务,特别是在使用像C这样的不支持大数运算的原生语言时。本项目的目标是编写一个小程序,能够处理非常大的整数的阶乘计算,并将结果存储到指定的输入文件中。这个程序的...
基本思想是将两个大数拆分为较小的部分,然后通过递归乘法和加法操作来计算它们的乘积。与简单的逐位相乘相比,Karatsuba算法的复杂度更低,是O(n^log2(3)),比O(n^2)的传统方法更高效。 另一个著名的算法是Toom-...
Karatsuba算法是一种分治策略,它将两个大数拆分成较小的部分,然后递归地进行乘法操作,降低了运算复杂度。Long multiplication则是通过将每个数字分解为位,逐位相乘再累加的方式。 为了实现这个带有界面的项目,...
其中,Karatsuba算法是一种效率较高的方法,它将两个大数拆分成较小的部分,然后递归地进行乘法操作,复杂度低于传统的乘法算法。 4. **VC 6.0环境**:微软的Visual C++ 6.0是较早的IDE,尽管已经过时,但在某些...
长乘法类似于手算乘法,将大数拆分成若干部分,逐项相乘然后累加结果。`BigInt`类的`BigInt operator*(const BigInt& other)`函数可以执行这个操作。 **除法**: 除法通常比加减乘法复杂。可以采用长除法算法,不断...
大数乘法的基本思想是分治策略,即把两个大数拆分成更小的部分,分别相乘,然后再将结果合并。最常见的算法是Karatsuba算法和Toom-Cook算法,这些算法比传统的学校乘法(也称为长乘法)更为高效。不过,对于非常大的...
在Java编程中,“单空间再拆分”可能指的是在有限的空间资源内,通过代码优化来高效地处理数据或存储结构。这个概念可能涉及到数组、集合、字符串或其他数据结构的拆分与重组。以下是对这个主题的详细解释: 一、...
1. **分治法(Divide and Conquer)**:将大数拆分为若干个较小的部分,然后对这些部分进行递归的乘方计算,最后合并结果。这种方法的代表是Karatsuba算法和Toom–Cook算法。 2. **位操作法**:通过位移、与、或...