問題描述:數組
最近遇到一個問題,在程序中,有一個百萬級別的商品集合,須要過濾掉商品黑名ide 單,這個黑名單由運營同窗手工配置,從原來的幾個到幾百個,再到上千個,致使現spa 在程序在過濾這塊耗時太長。如何使得程序的過濾運行時間縮短呢?日誌 |
分析:orm
好比,咱們的商品集合是Map<ID,Product> skuMap,ID爲商品的ID,Product是商品類型對象 對象,大小是100W+,商品黑名單列表是每隔10MIN去讀取一次造成long[] skus,數組的排序 元素放置的就是商品ID,數組大小是幾千級別。get 過濾方案:it 方案一: 僞碼: for(Product p : skuMap){ for(Long id : skus){ if(p.getId() == id){ //此商品被過濾掉 p.setFlag(false); } } } 這種方案,是最初的寫法,想法比較簡單,就是2層FOR循環。 可是,隨着配置的黑名單愈來愈多,從最初的幾個到幾百個,最後到幾千個級別,致使 這段代碼運行時間發生波動,而且愈來愈長! 方案二: 如何縮短期呢? 對於方案一,而言,100W+的商品中的每個商品都必須對skus進行所有遍歷才能完成過 濾邏輯,致使循環次數是 100W+ * 1000+ 級別,也就是10億+的級別,循環的次數實在 是太多了!要縮短循環次數,才能縮短期! 僞碼: Arrays.sort(skus); for(Product p : skuMap){ int result = Arrays.binarySearch(skus,id); if(result < 0){ p.setFlag(false); } } 若是咱們在拿到skus後,對skus內部的ID進行一次排序,而後每一個商品對skus進行二分 查找。要知道1000+的黑名單,對於二分查找而言,最多查找11次就能夠找到!也就是在 最壞的狀況下,咱們須要循環的次數變成了100W+ * 11,即1000W+的循環次數! 這樣方案二,一會兒將10億+的循環次數縮短至1000W+。 雖然如此,可是程序的過濾時間,日誌打印,居然是300S+,這也沒法接受! 方案三: 咱們爲何要拿skuMap取遍歷skus,爲何不用黑名單去過濾商品集合呢? 僞碼: for(long sku : skus){ if(skuMap.containsKey(sku)){ skuMap.get(sku).setFlag(false); } } 外層循環,變成了黑名單,在內部要知道咱們用的是HASHMAP查找,實際上,一會兒,循環次數變成了1000+。程序的過濾時間也縮短至幾秒鐘! |