避免双重for循环寻找相同条件拖慢查询速度

开发中我们会遇到以下这种场景:

我们通过查询条件,查询出两个不同实体的 list ,这两个实体通过一个外键id相关联,这时候我们要返回的这个实体中需要对应的另一个实体中的某一项值,这时候传统的思路是什么样的

	List<A> bigA=new ArraryList();
	List<B> bigB=new ArraryList();
	for(A aa :  bigA){
		forB bb : bigB){
			if(aa.getInfoId().equals(bb.getInfoId()){
				//如果是单项值 1对1 的操作
				aa.setForValue(bb.getForValue())
				//如果是多项值 1对多 的情况
				aa.setForValue( aa.getForValue + bb.getForValue ); 
			}
		}
	}
	return bigA;
	

存在问题

这样会存在大量的 for 循环存在,如果数据很少,则没有什么问题,但是当数据量多起来之后,这个接口很容易堵在这里,这还只是一个查找对应并进行取值和赋值,如果在循环中还有对数据库的查询操作那么就不止接口时间长的问题了,还会对数据库造成负担。

解决方法

为了避免大量的 for 循环存在,我们首先将外层 for 循环改成 stream 形式进行循环,这时候,内层肯定不能也只改成 stream 流的方式,这样双重循环并没有解决,这时候我们有两种情况

1.对比的这个 InfoId 对于 List 来说是唯一的,也就是单项值,1 对 1 的情况,那么这时候
//假设这个list
List<InfoResponse> infoList=...list的获取过程...
Map<Long, InfoResponse> resultMap = infoList.stream()
                    .filter(item -> item.getInfoId() != null)
                    .collect(Collectors.toMap(InfoResponse::getInfoId, data -> data));

如果你在这个id之下还有查询也可以

Map<Long, InfoResponse> resultMap = infoList.stream()
            .collect(Collectors.toMap(InfoResponse::getInfoId, entity -> {
                return mapper.selectById(entity.getId());
            }));

这样将list转化为 Map 之后,再进行另一个 list 的 for 循环时,就可以避免一次循环嵌套,例如

//另一个list,假设是个AInfoEntities 的list
List<AInfoEntities> aInfoEntities = ...
AInfoEntities result = aInfoEntities.stream().map(item -> {
           InfoResponse infoResponse= resultMap.get(item.getInfoId());
            item.setNewData(Objects.isNull(infoResponse) ? "0" : infoResponse.getNewData());
           return item;
        }).collect(Collectors.toList());

这样你就可以将第一个 list 其中的某项值根据 InfoId 设置进第一个 list ,并返回想要的 list 结果;

2. 对比的这个infoId 不是唯一值,在第二个list中存在多个的时候,也就是多项值的情况
Map<Long,List<InfoResponse>> resultMap = infoList.stream().collect(Collectors.groupingBy(InfoResponse::getInfoId));

或者如果你是只要知道map中key值对应的list的size的话

Map<Long,Long> resultMap = infoList.stream().collect(Collectors.groupingBy(InfoResponse::getInfoId,Collectors.counting()));

这样转化成map之后,再进行另一个list的循环赋值

//另一个list,假设是个AInfoEntities 的list
List<AInfoEntities> aInfoEntities = ...
AInfoEntities result = aInfoEntities.stream().map(item -> {
           List<InfoResponse> infoResponseList= resultMap.get(item.getInfoId());
           //直接list赋值
            item.setSonList(infoResponseList);
            //或者对list的操作
            Long count = infoResponseList.stream().filter(item-> item.getStatus() == 2).count();
            item.setNewDate(count);
           return item;
        }).collect(Collectors.toList());

这样我们就通过对其中一个list转化为map的操作,将双重for循环打破,变成单循环,单循环我们又通过使用stream流进行操作,如果你的单循环中只会有一个符合,还可以使用增加 break 的方法。

本人Java小白新手,如有不妥,还望包涵指正,谢谢!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值