隨筆-14  評(píng)論-25  文章-1  trackbacks-0
          在一個(gè)項(xiàng)目里面有這么一個(gè)技術(shù)需求:
          1.集合中元素個(gè)數(shù),10M
          2.根據(jù)上限和下限從一個(gè)Set中過(guò)濾出滿足要求的元素集合.

          實(shí)際這個(gè)是個(gè)很典型的技術(shù)要求, 之前的項(xiàng)目也遇見(jiàn)過(guò),但是因?yàn)楫?dāng)時(shí)的類庫(kù)不多, 都是直接手寫(xiě)實(shí)現(xiàn)的. 方式基本等同于第一個(gè)方式.

          在這個(gè)過(guò)程中, 我寫(xiě)了四個(gè)方式, 基本記錄到下面.
          第一個(gè)方式:對(duì)Set進(jìn)行迭代器遍歷, 判斷每個(gè)元素是否都在上限和下限范圍中.如果滿足則添加到結(jié)果集合中, 最后返回結(jié)果集合.
                      測(cè)試效果:集合大小100K, 運(yùn)算時(shí)間 3000ms+
          過(guò)濾部分的邏輯如下:
           1     void filerSet(Set<BigDecimal> targetSet, String lower, String higher) {
           2         BigDecimal bdLower = new BigDecimal(Double.parseDouble(lower));
           3         BigDecimal bdHigher = new BigDecimal(Double.parseDouble(higher));
           4 
           5         Set<BigDecimal> returnSet = new HashSet<BigDecimal>();
           6         for (BigDecimal object : targetSet) {
           7             if (isInRange(object, bdLower, bdHigher)) {
           8                 returnSet.add(object);
           9             }
          10         }
          11     }
          12 
          13     private boolean isInRange(BigDecimal object, BigDecimal bdLower,
          14             BigDecimal bdHigher) {
          15         return object.compareTo(bdLower) >= 0
          16                 && object.compareTo(bdHigher) <= 0;
          17     }
          第二個(gè)方式: 借助TreeSet, 原始集合進(jìn)行排序, 然后直接subset.
                      測(cè)試效果: 集合大小10M, 運(yùn)算時(shí)間: 12000ms+(獲得TreeSet) , 200ms(獲得結(jié)果)
          過(guò)濾部分的邏輯如下(非常繁瑣):
            1     Set<BigDecimal> getSubSet(TreeSet<BigDecimal> targetSet, String lower,
            2             String higher) {
            3 
            4         BigDecimal bdLower = new BigDecimal(Double.parseDouble(lower));
            5         BigDecimal bdHigher = new BigDecimal(Double.parseDouble(higher));
            6 
            7         if ((bdHigher.compareTo(targetSet.first()) == -1)
            8                 || (bdLower.compareTo(targetSet.last()) == 1)) {
            9             return null;
           10         }
           11 
           12         boolean hasLower = targetSet.contains(bdLower);
           13         boolean hasHigher = targetSet.contains(bdHigher);
           14         if (hasLower) {
           15             if (hasHigher) {
           16                 System.out.println("get start:" + bdLower);
           17                 System.out.println("get end:" + bdHigher);
           18                 return targetSet.subSet(bdLower, true, bdHigher, true);
           19             } else {
           20                 BigDecimal newEnd = null;
           21                 System.out.println("get start:" + bdLower);
           22                 SortedSet<BigDecimal> returnSet = null;
           23                 if (bdHigher.compareTo(targetSet.last()) != -1) {
           24                     newEnd = targetSet.last();
           25                 } else {
           26                     SortedSet<BigDecimal> newTargetSet = targetSet
           27                             .tailSet(bdLower);
           28                     for (BigDecimal object : newTargetSet) {
           29                         if (object.compareTo(bdHigher) == 1) {
           30                             newEnd = object;
           31                             break;
           32                         } else if (object.compareTo(bdHigher) == 0) {
           33                             newEnd = object;
           34                             break;
           35                         }
           36                     }
           37                 }
           38                 returnSet = targetSet.subSet(bdLower, true, newEnd, true);
           39                 if (newEnd.compareTo(bdHigher) == 1) {
           40                     returnSet.remove(newEnd);
           41                 }
           42                 return returnSet;
           43             }
           44 
           45         } else {
           46             if (hasHigher) {
           47                 System.out.println("get end:" + bdHigher);
           48                 TreeSet<BigDecimal> newTargetSet = (TreeSet<BigDecimal>) targetSet
           49                         .headSet(bdHigher, true);
           50                 BigDecimal newStart = null;
           51                 SortedSet<BigDecimal> returnSet = null;
           52 
           53                 if (bdLower.compareTo(targetSet.first()) == -1) {
           54                     newStart = targetSet.first();
           55                 } else {
           56                     for (BigDecimal object : newTargetSet) {
           57                         if (object.compareTo(bdLower) != -1) {
           58                             newStart = object;
           59                             break;
           60                         }
           61                     }
           62                 }
           63                 returnSet = targetSet.subSet(newStart, true, bdHigher, true);
           64 
           65                 return returnSet;
           66             } else {
           67                 System.out.println("Not get start:" + bdLower);
           68                 System.out.println("Not get end:" + bdHigher);
           69                 BigDecimal newStart = null;
           70                 BigDecimal newEnd = null;
           71                 if (bdHigher.compareTo(targetSet.last()) != -1) {
           72                     newEnd = targetSet.last();
           73                 }
           74                 if (bdLower.compareTo(targetSet.first()) == -1) {
           75                     newStart = targetSet.first();
           76                 }
           77                 for (BigDecimal object : targetSet) {
           78                     if (newStart == null) {
           79                         if (object.compareTo(bdLower) != -1) {
           80                             newStart = object;
           81                             if (newEnd != null) {
           82                                 break;
           83                             }
           84                         }
           85                     }
           86 
           87                     if (newEnd == null) {
           88                         if (object.compareTo(bdHigher) != -1) {
           89                             newEnd = object;
           90                             if (newStart != null) {
           91                                 break;
           92                             }
           93                         }
           94                     }
           95                 }
           96 
           97                 if (newStart == null) {
           98                     if (newEnd == null) {
           99                         if ((bdHigher.compareTo(targetSet.first()) == -1)
          100                                 || (bdLower.compareTo(targetSet.last()) == 1)) {
          101                             return null;
          102                         }
          103                         return targetSet;
          104                     } else {
          105                         SortedSet<BigDecimal> newTargetSet = targetSet.headSet(
          106                                 newEnd, true);
          107                         if (newEnd.compareTo(bdHigher) == 1) {
          108                             newTargetSet.remove(newEnd);
          109                         }
          110                         return newTargetSet;
          111                     }
          112                 } else {
          113                     if (newEnd == null) {
          114                         SortedSet<BigDecimal> newTargetSet = targetSet.tailSet(
          115                                 newStart, true);
          116                         return newTargetSet;
          117                     } else {
          118                         SortedSet<BigDecimal> newTargetSet = targetSet.subSet(
          119                                 newStart, true, newEnd, true);
          120                         if (newEnd.compareTo(bdHigher) == 1) {
          121                             newTargetSet.remove(newEnd);
          122                         }
          123                         return newTargetSet;
          124                     }
          125                 }
          126             }
          127         }
          128     }
          第三種方式: 使用Apache Commons Collections, 直接對(duì)于原始Set進(jìn)行filter.
                      測(cè)試效果:集合大小10M,過(guò)濾結(jié)果1M, 運(yùn)算時(shí)間: 1000ms+
          過(guò)濾部分的代碼如下:
           1 //過(guò)濾的主體邏輯
           2     void filterSet(Set<BigDecimal> targetSet, String lower, String higher) {
           3         final BigDecimal bdLower = new BigDecimal(Double.parseDouble(lower));
           4         final BigDecimal bdHigher = new BigDecimal(Double.parseDouble(higher));
           5 
           6         Predicate predicate = new Predicate() {
           7             public boolean evaluate(Object object) {
           8                 BigDecimal bDObject = (BigDecimal) object;
           9                 return bDObject.compareTo(bdLower) >= 0
          10                         && bDObject.compareTo(bdHigher) <= 0;
          11             }
          12         };
          13 
          14         CollectionUtils.filter(targetSet, predicate);
          15     }

          第四種方式:使用Guava(google Collections), 直接對(duì)于原始Set進(jìn)行Filter
                      測(cè)試效果:集合大小10M,過(guò)濾結(jié)果1M, 運(yùn)算時(shí)間: 100ms-
          過(guò)濾部分的代碼如下:
           1 //guava filter
           2 
           3     Set<BigDecimal> filterSet(Set<BigDecimal> targetSet, String lower,
           4             String higher) {
           5         final BigDecimal bdLower = new BigDecimal(Double.parseDouble(lower));
           6         final BigDecimal bdHigher = new BigDecimal(Double.parseDouble(higher));
           7 
           8         Set<BigDecimal> filterCollection = Sets.filter(targetSet,
           9                 new Predicate<BigDecimal>() {
          10                     @Override
          11                     public boolean apply(BigDecimal input) {
          12                         BigDecimal bDObject = (BigDecimal) input;
          13                         return bDObject.compareTo(bdLower) >= 0
          14                                 && bDObject.compareTo(bdHigher) <= 0;
          15                     }
          16                 });
          17 
          18         return filterCollection;
          19     }


          四種方式對(duì)比如下:
          第一種方式:  僅依賴于JAVA原生類庫(kù) 遍歷時(shí)間最慢, 代碼量很小
          第二種方式:  僅依賴于JAVA原生類庫(kù) 遍歷時(shí)間比較慢(主要慢在生成有序Set), 代碼量最多
          第三種方式:  依賴于Apache Commons Collections, 遍歷時(shí)間比較快, 代碼量很少
          第四種方式:  依賴于Guava, 遍歷時(shí)間最快, 代碼量很少

          基于目前個(gè)人的技術(shù)水平和視野, 第四種方式可能是最佳選擇.

          記錄一下, 以后可能還會(huì)有更好的方案.




          posted on 2014-06-21 23:33 混沌中立 閱讀(7373) 評(píng)論(10)  編輯  收藏 所屬分類: about java & j2ee

          評(píng)論:
          # re: 一個(gè)簡(jiǎn)單的Java集合范圍過(guò)濾的多個(gè)方式對(duì)比 2014-06-22 18:07 | java論壇
          運(yùn)行效率好像沒(méi)多大差別哈

          http://www.itqx.net  回復(fù)  更多評(píng)論
            
          # re: 一個(gè)簡(jiǎn)單的Java集合范圍過(guò)濾的多個(gè)方式對(duì)比 2014-06-22 18:59 | 混沌中立
          第一個(gè)方式是10萬(wàn)數(shù)據(jù), 3000+ms,
          第二種是1千萬(wàn),12000ms
          第三種是1千萬(wàn), 3000ms
          第四種是1千萬(wàn), 100ms

          第一種和第四種比較的話, 可能有三個(gè)量級(jí)的區(qū)別, 區(qū)別巨大.

          @java論壇
            回復(fù)  更多評(píng)論
            
          # re: 一個(gè)簡(jiǎn)單的Java集合范圍過(guò)濾的多個(gè)方式對(duì)比 2014-06-23 00:07 | 亞歷山大
          guava并沒(méi)有立即執(zhí)行,而是緩執(zhí)行,遍歷下就知道了。無(wú)序的話,無(wú)論如何復(fù)雜度都是N。  回復(fù)  更多評(píng)論
            
          # re: 一個(gè)簡(jiǎn)單的Java集合范圍過(guò)濾的多個(gè)方式對(duì)比 2014-06-23 10:43 | 金利鎖業(yè)
          謝謝博主更新  回復(fù)  更多評(píng)論
            
          # re: 一個(gè)簡(jiǎn)單的Java集合范圍過(guò)濾的多個(gè)方式對(duì)比 2014-06-23 11:39 | java論壇
          @混沌中立

          謝謝
            回復(fù)  更多評(píng)論
            
          # re: 一個(gè)簡(jiǎn)單的Java集合范圍過(guò)濾的多個(gè)方式對(duì)比 2014-06-23 21:55 | 混沌中立
          確實(shí)有這種可能,
          但是 四種方式中size()的結(jié)果都是一致的.
          @亞歷山大
            回復(fù)  更多評(píng)論
            
          # re: 一個(gè)簡(jiǎn)單的Java集合范圍過(guò)濾的多個(gè)方式對(duì)比 2014-06-24 05:35 | 金利鎖業(yè)
          歡迎回訪啊  回復(fù)  更多評(píng)論
            
          # re: 一個(gè)簡(jiǎn)單的Java集合范圍過(guò)濾的多個(gè)方式對(duì)比 2014-07-08 10:03 | 博客寫(xiě)什么
          高技術(shù)含量博客  回復(fù)  更多評(píng)論
            
          # re: 一個(gè)簡(jiǎn)單的Java集合范圍過(guò)濾的多個(gè)方式對(duì)比 2014-07-08 20:27 | 旺達(dá)鎖業(yè)
          謝謝你只關(guān)心  回復(fù)  更多評(píng)論
            
          # re: 一個(gè)簡(jiǎn)單的Java集合范圍過(guò)濾的多個(gè)方式對(duì)比 2014-07-19 14:56 | 個(gè)人品牌
          不大理解  回復(fù)  更多評(píng)論
            
          主站蜘蛛池模板: 瑞昌市| 广饶县| 杨浦区| 藁城市| 牡丹江市| 蓬安县| 娱乐| 闽侯县| 尼勒克县| 塘沽区| 双鸭山市| 柯坪县| 磐石市| 茌平县| 正阳县| 灵山县| 双鸭山市| 云霄县| 大城县| 循化| 涪陵区| 丰城市| 正定县| 信丰县| 政和县| 建始县| 温州市| 忻城县| 襄垣县| 永修县| 疏勒县| 尼勒克县| 化德县| 马鞍山市| 民权县| 浮梁县| 义乌市| 沛县| 汝阳县| 阳信县| 讷河市|