在一个项目里面有这么一个技术需求:
1.集合中元素个数,10M
2.根据上限和下限从一个Set中过滤出满足要求的元素集合.

实际这个是个很典型的技术要求, 之前的项目也遇见过,但是因为当时的类库不多, 都是直接手写实现的. 方式基本等同于第一个方式.

在这个过程中, 我写了四个方式, 基本记录到下面.
第一个方式:对Set进行迭代器遍历, 判断每个元素是否都在上限和下限范围中.如果满足则添加到结果集合中, 最后返回结果集合.
            测试效果:集合大小100K, 运算时间 3000ms+
过滤部分的逻辑如下:

 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     }

第二个方式: 借助TreeSet, 原始集合进行排序, 然后直接subset.
            测试效果: 集合大小10M, 运算时间: 12000ms+(获得TreeSet) , 200ms(获得结果)
过滤部分的逻辑如下(非常繁琐):

  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, 直接对于原始Set进行filter.
            测试效果:集合大小10M,过滤结果1M, 运算时间: 1000ms+
过滤部分的代码如下:

 1 //过滤的主体逻辑
 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   /* CollectionUtils.filter(targetSet, new Predicate() {
16    @Override
17    public boolean evaluate(Object o) {
18    BigDecimal bDObject = (BigDecimal) o;
19     return bDObject.compareTo(bdLower) >= 0
10                         && bDObject.compareTo(bdHigher) <= 0;
20    }
21    });*/
22     }

第四种方式:使用Guava(google Collections), 直接对于原始Set进行Filter
            测试效果:集合大小10M,过滤结果1M, 运算时间: 100ms-
过滤部分的代码如下:

 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     }

四种方式对比如下:
第一种方式:  仅依赖于JAVA原生类库 遍历时间最慢, 代码量很小
第二种方式:  仅依赖于JAVA原生类库 遍历时间比较慢(主要慢在生成有序Set), 代码量最多
第三种方式:  依赖于Apache Commons Collections, 遍历时间比较快, 代码量很少
第四种方式:  依赖于Guava, 遍历时间最快, 代码量很少

基于目前个人的技术水平和视野, 第四种方式可能是最佳选择.

记录一下, 以后可能还会有更好的方案.

一个简单的Java集合范围过滤的多个方式对比的更多相关文章

  1. 一个简单的Java web服务器实现

    前言 一个简单的Java web服务器实现,比较简单,基于java.net.Socket和java.net.ServerSocket实现: 程序执行步骤 创建一个ServerSocket对象: 调用S ...

  2. Java学习笔记 11/15:一个简单的JAVA例子

    首先来看一个简单的 Java 程序. 来看下面这个程序,试试看是否看得出它是在做哪些事情! 范例:TestJava.java   // TestJava.java,java 的简单范例  public ...

  3. Java入门篇(一)——如何编写一个简单的Java程序

    最近准备花费很长一段时间写一些关于Java的从入门到进阶再到项目开发的教程,希望对初学Java的朋友们有所帮助,更快的融入Java的学习之中. 主要内容包括JavaSE.JavaEE的基础知识以及如何 ...

  4. Ant—使用Ant构建一个简单的Java工程(两)

    博客<Ant-使用Ant构建一个简单的Java项目(一)>演示了使用Ant工具构建简单的Java项目,接着这个样例来进一步学习Ant: 上面样例须要运行多条ant命令才干运行Test类中的 ...

  5. IntelliJ IDEA创建一个简单的Java Project(二)

    1.  选择要创建的项目类型,同时配置本地的JDK 2. 是否使用模板创建项目 3. 选择项目在本地的存储位置 4. 点击Finish,完成一个简单的Java工程的创建.

  6. 利用 Docker 构建一个简单的 java 开发编译环境

    目前 Java 语言的版本很多,除了常用的 Java 8,有一些遗留项目可能使用了 Java 7,也可能有一些比较新的的项目使用了 Java 10 以上的版本.如果想切换自己本地的 Java 开发环境 ...

  7. 【Java】一个简单的Java应用程序

    简单记录,Java 核心技术卷I 基础知识(原书第10 版) 一个简单的Java应用程序"Hello, World!" Hello, World! Goodbye,World! 一 ...

  8. 一个简单的Java应用程序

    目录 一个简单的Java应用程序 首次运行结果 程序示例 运行结果 修改大小写之后的运行结果 程序示例 运行结果 关键字public 关键字class 类名及其命名规则 类名必须以字母开头 不能使用J ...

  9. 从一个简单的Java单例示例谈谈并发

    一个简单的单例示例 单例模式可能是大家经常接触和使用的一个设计模式,你可能会这么写 public class UnsafeLazyInitiallization { private static Un ...

随机推荐

  1. Android开源项目收集

    软件名:gaeproxy软件作用:Android手机配置GoAgentFQ.项目地址:https://github.com/madeye/gaeproxy.git 软件名:ProxyDroid软件作用 ...

  2. win7 64位andriod开发环境搭建

    本文转自:http://www.cfanz.cn/index.php?c=article&a=read&id=65289 最近换了新电脑,装了win7 64位系统,安装了各种开发环境, ...

  3. 集合-字典(Dictionary)

    字典(散列表):允许按照某个键来访问元素,能根据键快速查找元素,也可以自由添加,删除元素.比较像List<T>类,但没有list向后移动元素的性能开销. .net中最主要的字典类是Dict ...

  4. JSDOM优化

    JS操作DOM,就像从一个岛到另外一个岛,过桥的时候,每次都要收取过桥费,尽量减少过桥的次数.列如:   for循环插入到页面5000个LI:  应该 先用一个变量存 5000个li,然后一次插入. ...

  5. STM32的优先级NVIC_PriorityGroupConfig的理解及其使用(转)

    源:http://blog.csdn.net/yx_l128125/article/details/9703843 写作原由:因为之前有对stm32 优先级做过研究,但是没时间把整理的东西发表,最近项 ...

  6. window下查看端口命令

    原文:http://blog.csdn.net/ldl22847/article/details/7181210 http://blog.csdn.net/xinxin19881112/article ...

  7. Java中的局部内部类

    package Smoke; public class Inner { private int num = 3; class Limian{ public void show(){ //内部类可以访问 ...

  8. CSS文字垂直居中和font-family属性

    1.单行文字的垂直居中 单行文字垂直居中比较简单,直接让行高==盒子高度即可. 2.多行文字居中 多行文字居中,只需简单计算一下盒子的上padding即可.计算公式:padding-top=(盒子的高 ...

  9. Charles从入门到精通

    Charles 从入门到精通 发表于 2015-11-14 12:00 文章目录 1. 目录 2. 简介 3. 安装 Charles 4. 将 Charles 设置成系统代理 5. Charles 主 ...

  10. (中等) HDU 5293 Tree chain problem,树链剖分+树形DP。

    Problem Description   Coco has a tree, whose vertices are conveniently labeled by 1,2,…,n.There are ...