Salesforce 如何替换嵌套for循环映射,以及如何减少计算部分的时间?
如何用map替换嵌套for循环 如何用映射替换嵌套的FOR循环 公共类案例{ public void calculatetimeList caseids,Map casemap{Salesforce 如何替换嵌套for循环映射,以及如何减少计算部分的时间?,salesforce,Salesforce,如何用map替换嵌套for循环 如何用映射替换嵌套的FOR循环 公共类案例{ public void calculatetimeList caseids,Map casemap{ map<string,List<CaseMilestone>> milestonemap = new map<string,List<CaseMilestone>>(); if(casemap!=null && caseids.size()
map<string,List<CaseMilestone>> milestonemap = new map<string,List<CaseMilestone>>();
if(casemap!=null && caseids.size()>0){
BusinessHours bh = [SELECT Id FROM BusinessHours WHERE IsDefault=true];
List<Case> caselist = [Select id, (select caseId,id,isCompleted,MilestoneTypeId,BusinessHoursId,MilestoneType.name,CompletionDate from
CaseMilestones where(MilestoneType.name='First Response' or MilestoneType.name='Technical Resolution')
AND caseid IN:casemap.keySet()) from case];
for(Case cs: caselist ){
milestonemap.put(cs.id,cs.Casemilestones);
}
for(Case c: caseids){
if(c.Request_for_Closure_Date__c!=null && milestonemap.containskey(c.id) ){
for(CaseMilestone ml:milestonemap.get(c.id)){
if(ml.MilestoneType.name=='First Response'){
Integer ms = Integer.valueOf((BusinessHours.diff(bh.id, ml.CompletionDate, c.Request_for_Closure_Date__c))/1000);
system.debug('Time@calculation'+ms);
Integer sec = ms;
Integer mns = sec/60;
integer days = mns / 60 / 24 ;
integer hours = (mns - days * 60 * 24) / 60 ;
integer mins = mns - days * 60 * 24 - hours * 60 ;
String timeSpentOnCase = days+'Days '+hours+'Hours '+mins+'Minutes'+sec+'Secs';
System.debug('Time'+timeSpentOnCase);
c.Test_Ignore__c = ml.CompletionDate;
}
else if(ml.MilestoneType.name=='Technical Resolution'){
c.Test_Ignore_2__c = ml.CompletionDate;
}
}
}
}
}
}
}这些循环已经过优化,但实际上不需要基于地图的数据访问,因为子对象是通过父对象查询的
for(Case cs: caselist ){
milestonemap.put(cs.id,cs.Casemilestones);
}
这完全不需要,可以删除。相反,更改内部for循环以直接引用子事例里程碑列表
for(Case c: caseids){
if(c.Request_for_Closure_Date__c!=null){
for(CaseMilestone ml : c.CaseMilestones){
如果c.case为空,循环就不会执行
这段代码没有进一步的基于地图的优化。正如David在上面的评论中所说的,访问已经相当优化了。 如果您寻求进一步优化,我会: 移动ifc.Request\u for\u Closure\u Date\u c!=null并改进WHERE子句,如果在处理过程中跳过某些案例,为什么要检索它们
SELECT Id,
(SELECT CaseId, Id, isCompleted...
FROM CaseMilestones
WHERE ...)
FROM Case
WHEREId IN :caseids AND Request_for_Closure_Date__c!=null
扔掉这些代码。如果只是为了system.debug,那就是在浪费计算时间
Integer ms = Integer.valueOf((BusinessHours.diff(bh.id, ml.CompletionDate, c.Request_for_Closure_Date__c))/1000);
system.debug('Time@calculation'+ms);
Integer sec = ms;
Integer mns = sec/60;
integer days = mns / 60 / 24 ;
integer hours = (mns - days * 60 * 24) / 60 ;
integer mins = mns - days * 60 * 24 - hours * 60 ;
String timeSpentOnCase = days+'Days '+hours+'Hours '+mins+'Minutes'+sec+'Secs';
System.debug('Time'+timeSpentOnCase);
如果在这两次优化之后,您仍然存在性能问题,那么您可能必须重新考虑您的业务逻辑和查询。是否保证每种情况下最多有一个里程碑
也许您需要一个只包含一种类型的子查询来提供最新的里程碑?类似于选择Id,从CaseModels中选择CompletionDate,其中type='x'ORDER BY CompletionDate DESC LIMIT 1 FROM Case?然后您对第二种类型和流程运行此查询。好的,浪费2个查询,但保证只返回几行
或者,您可以通过执行以下操作完全简化此代码
SELECT CaseId, MAX(CompletionDate) d, MilestoneType.Name t
FROM CaseMilestone
WHERE CaseId IN :... AND MilestoneType.Name IN :...
GROUP BY CaseId, MilestoneType.Name
谢谢你们两位,如果case没有任何里程碑,我如何修改我的代码以停止执行查询。在最初的一个查询之后,您没有进行任何查询。我不确定您在问什么。如果我的case没有里程碑,我如何停止执行这两个查询。如何提前检查。您的意思是传递给函数的参数?modify t他查询说SELECT Id,…FROM Case WHERE…和SELECT CaseId FROM CASEMENTOLLESTONE中的Id。它应该可以很好地立即过滤掉相关列表中没有任何内容的情况。如果这仍然会给您带来性能问题-有些严重错误,但可能在其他地方。您必须在调试日志中计时,以查看真正的问题在哪里瓶颈是。如果我的案例没有任何里程碑,并且“请求关闭日期”或“技术解决方案”或“固定日期”被更改,我的查询将运行。是否有方法停止执行这些查询