引言
最近在老系統中看到了一大段代碼,這個代碼的目的是遷移遷移歷史,在遷移的過程中需要很多計算,我大概看了一下代碼,裏面到處都是for 循環,雖然for循環的邏輯比較簡單,但是循環的次數太多了, 這就導致這個方法非常的慢,其中有一個地方就是通過循環獲得日期。
如果list中有5000個日期,恰好這個要查找的日期在最後面一個,那麼肯定完蛋。 如果通過二分查找肯定會會少很多循環。
目標:找到集合中早於目標日期,並且最接近的一個日期,如果沒有早於的則不返回
代碼:
package com.zqf.platformweb.statistics.service;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
/**
* @author zhenghao
* @description:
* @date 2020/6/2118:45
*/
public class test {
public static void main(String[] args) throws Exception {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
Integer c = 0;
//需要一個有序且不重複的數組
List<Date> number = new ArrayList<>();
number.add(sdf.parse("2010-04-10"));
number.add(sdf.parse("2013-03-14"));
number.add(sdf.parse("2015-07-18"));
number.add(new Date());
number.add(sdf.parse("2025-07-16"));
System.out.println(find(number, 0, number.size()-1, sdf.parse("2025-07-16"), c));
}
public static Date find(List<Date> number, Integer start, Integer end, Date k, Integer c){
c++;
//如果只剩一個 直接返回
if (start.equals(end)){
Date startN = number.get(start);
if (!startN.after(k)){
return startN;
}
return null;
}
//如果只剩兩個 返回最小的那個
if (Math.abs(start-end) == 1){
Date startN = number.get(start);
Date endN = number.get(end);
if (!endN.after(k)){
return endN;
}
if (!startN.after(k)){
return startN;
}
return null;
}
int midle = (start + end)/2;
Date right = number.get(midle+1);
//如果左邊差值 比 右邊差值 小 遞歸左半部分
if (!right.after(k)){
return find(number, midle + 1, end, k, c);
}else {
return find(number, start, midle , k, c);
}
}
}
經過測試,效果有很多提升,各位讀者可以根據自己的需求,採用合適的算法來提升性能。
總結
如果能深入的瞭解數據結構和算法,在代碼性能優化方面會有更多的思路,效果也會有明顯提升。