`
tomkoo
  • 浏览: 187153 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

List数据对比筛选,如何才能达到最佳效率?

 
阅读更多
在实际的开发中,经常会晕倒这样的问题,有两个List的数据,需要对这两个List的数据进行对比,然后筛选出需要的对象。

例如:财务中的对账,数据源一个是银行日记账(aList),一个是银行对帐单(bList),业务操作就是把两个List里面金额相同的记录筛选掉,剩下金额不相等的。

在实际开发中我目前知道有两个方式(假设两个List各有1000条数据):

1、最简单的就是用双重循环进行比较,虽然简单,但是如果两个List的数据量都很大,那么运行时间将成数量级增长。循环次数为1000*1000

2、把一个List通过循环放入Map中,把需要比较的字段作为Map的Key,然后循环另外一个List,到Map里面去匹配。

for(A a : aList){
   map.put(a.amount,a);
}

for(B b : bList){
   A a = map.get(b.amount);
   if(a==null){
      //a==null则说明没有同b匹配的项
   }else{
      //a!=null则说明匹配上了
   }
}


由于在Map中取数非常快,主要的耗时就在业务处理和循环上。循环次数为1000*2

但是第2种方法还是有不足的地方:

1、当比较的值有相同的时候,由于Key必须唯一,所以后面的值会覆盖掉前面的数据
2、当比较的内容比较复杂,或者是多项的时候,就比较难处理


我想在平时开发中大家应该都会遇到这样的问题吧,不知道大家有没有更好的方法来解决这个问题!!
分享到:
评论
12 楼 抛出异常的爱 2008-01-18  
要想对的快....要把list先排了序才可以...
用set treemap之类的东西存放数据
这样才不用每次遍历
11 楼 red008 2008-01-18  
把2个list都加到一个新的set中去,这个set里面就全是不重复的数据了。
代码只需要2行,看着也舒服。
10 楼 Godlikeme 2008-01-18  
tomkoo 写道
在实际的开发中,经常会晕倒这样的问题,有两个List的数据,需要对这两个List的数据进行对比,然后筛选出需要的对象。

例如:财务中的对账,数据源一个是银行日记账(aList),一个是银行对帐单(bList),业务操作就是把两个List里面金额相同的记录筛选掉,剩下金额不相等的。

在实际开发中我目前知道有两个方式(假设两个List各有1000条数据):

1、最简单的就是用双重循环进行比较,虽然简单,但是如果两个List的数据量都很大,那么运行时间将成数量级增长。循环次数为1000*1000

2、把一个List通过循环放入Map中,把需要比较的字段作为Map的Key,然后循环另外一个List,到Map里面去匹配。

for(A a : aList){
   map.put(a.amount,a);
}

for(B b : bList){
   A a = map.get(b.amount);
   if(a==null){
      //a==null则说明没有同b匹配的项
   }else{
      //a!=null则说明匹配上了
   }
}


由于在Map中取数非常快,主要的耗时就在业务处理和循环上。循环次数为1000*2

但是第2种方法还是有不足的地方:

1、当比较的值有相同的时候,由于Key必须唯一,所以后面的值会覆盖掉前面的数据
2、当比较的内容比较复杂,或者是多项的时候,就比较难处理


我想在平时开发中大家应该都会遇到这样的问题吧,不知道大家有没有更好的方法来解决这个问题!!


第一种方法, 两个列表金额为Key,List为Value往 HashMap里面放就可以了。O(2n)
这种问题自己思考下吧,不要总期望找现成的。
9 楼 hamlet 2007-10-17  
CollectionUtils 好像不能满足lz的需求吧,
lz的意思是按照数据对象的某一属性进行比较,
而CollectionUtils中 则是按照对象在内存中的Id进行比较,
得到的结果很有可能会不同,除非重写数据对象的equal()方法。
看看CollectionUtils 的getCardinalityMap方法和getFreq()方法就知道了
public static Map getCardinalityMap(final Collection col) {
        HashMap count = new HashMap();
        Iterator it = col.iterator();
        while(it.hasNext()) {
            Object obj = it.next();
            Integer c = (Integer)(count.get(obj));
            if(null == c) {
                count.put(obj,new Integer(1));
            } else {
                [b]count.put(obj,new Integer(c.intValue() + 1))[/b];
            }
        }
        return count;
    }


private static final int getFreq(final Object obj, final Map freqMap) {
        try {
            return ((Integer)([b]freqMap.get(obj)[/b])).intValue();
        } catch(NullPointerException e) {
            // ignored
        } catch(NoSuchElementException e) {
            // ignored
        }
        return 0;
    }
8 楼 lighter 2007-10-15  
phantomhu 写道

Collections是那个包里面的 java.util.Collections的sort不能用在Collection对象上啊

嗯,你说的对,可以强制转化一下,呵呵:
Collections.sort((List)union);
Collections.sort((List)intersection);
Collections.sort((List)disjunction);
Collections.sort((List)subtract);
7 楼 phantomhu 2007-10-15  
lighter 写道
tomkoo 写道
Comparable实现排序,比较时还是需要循环啊

Commons 里面可能有你想要的答案,看一下CollectionUtils类吧
String[] arrayA = new String[] { "1", "2", "3", "3", "4", "5" };
String[] arrayB = new String[] { "3", "4", "4", "5", "6", "7" };

List a = Arrays.asList( arrayA );
List b = Arrays.asList( arrayB );

Collection union = CollectionUtils.union( a, b );
Collection intersection = CollectionUtils.intersection( a, b );
Collection disjunction = CollectionUtils.disjunction( a, b );
Collection subtract = CollectionUtils.subtract( a, b );

Collections.sort( union );
Collections.sort( intersection );
Collections.sort( disjunction );
Collections.sort( subtract );


System.out.println( "A: " + ArrayUtils.toString( a.toArray( ) ) );
System.out.println( "B: " + ArrayUtils.toString( b.toArray( ) ) );
System.out.println( "Union: " + ArrayUtils.toString( union.toArray( ) ) );
System.out.println( "Intersection: " + 
                    ArrayUtils.toString( intersection.toArray( ) ) );
System.out.println( "Disjunction: " + 
                    ArrayUtils.toString( disjunction.toArray( ) ) );
System.out.println( "Subtract: " + ArrayUtils.toString( subtract.toArray( ) ) );


The previous example performs these four operations on two List objects, a and b, printing the results with ArrayUtils.toString( ):

A: {1,2,2,2,3,3,4,5}
B: {3,4,4,5,6,7}
Union: {1,2,2,2,3,3,4,4,5,6,7}
Intersection: {3,4,5}
Disjunction: {1,2,2,2,3,4,6,7}
Subtract: {1,2,2,2,3}




Collections是那个包里面的 java.util.Collections的sort不能用在Collection对象上啊
6 楼 tomkoo 2007-10-13  
抽出时间看了一下ColletionUtils类的源代码,发现,union,intersection,disjunction,subtract等方法的实现方式都是我前面提到的第二种方式,利用Map来进行一系列的比较操作。不过用得可比我的例子灵活多了。看了有种豁然开朗的感觉。

谢谢楼上的!
5 楼 tomkoo 2007-10-13  
lighter 写道
tomkoo 写道
Comparable实现排序,比较时还是需要循环啊

Commons IO 里面可能有你想要的答案,看一下CollectionUtils类吧
String[] arrayA = new String[] { "1", "2", "3", "3", "4", "5" };
String[] arrayB = new String[] { "3", "4", "4", "5", "6", "7" };

List a = Arrays.asList( arrayA );
List b = Arrays.asList( arrayB );

Collection union = CollectionUtils.union( a, b );
Collection intersection = CollectionUtils.intersection( a, b );
Collection disjunction = CollectionUtils.disjunction( a, b );
Collection subtract = CollectionUtils.subtract( a, b );

Collections.sort( union );
Collections.sort( intersection );
Collections.sort( disjunction );
Collections.sort( subtract );


System.out.println( "A: " + ArrayUtils.toString( a.toArray( ) ) );
System.out.println( "B: " + ArrayUtils.toString( b.toArray( ) ) );
System.out.println( "Union: " + ArrayUtils.toString( union.toArray( ) ) );
System.out.println( "Intersection: " + 
                    ArrayUtils.toString( intersection.toArray( ) ) );
System.out.println( "Disjunction: " + 
                    ArrayUtils.toString( disjunction.toArray( ) ) );
System.out.println( "Subtract: " + ArrayUtils.toString( subtract.toArray( ) ) );


The previous example performs these four operations on two List objects, a and b, printing the results with ArrayUtils.toString( ):

A: {1,2,2,2,3,3,4,5}
B: {3,4,4,5,6,7}
Union: {1,2,2,2,3,3,4,4,5,6,7}
Intersection: {3,4,5}
Disjunction: {1,2,2,2,3,4,6,7}
Subtract: {1,2,2,2,3}



还真的没有好好使用过CollectionUtils,谢谢!这就看去!
4 楼 lighter 2007-10-13  
tomkoo 写道
Comparable实现排序,比较时还是需要循环啊

Commons 里面可能有你想要的答案,看一下CollectionUtils类吧
String[] arrayA = new String[] { "1", "2", "3", "3", "4", "5" };
String[] arrayB = new String[] { "3", "4", "4", "5", "6", "7" };

List a = Arrays.asList( arrayA );
List b = Arrays.asList( arrayB );

Collection union = CollectionUtils.union( a, b );
Collection intersection = CollectionUtils.intersection( a, b );
Collection disjunction = CollectionUtils.disjunction( a, b );
Collection subtract = CollectionUtils.subtract( a, b );

Collections.sort( union );
Collections.sort( intersection );
Collections.sort( disjunction );
Collections.sort( subtract );


System.out.println( "A: " + ArrayUtils.toString( a.toArray( ) ) );
System.out.println( "B: " + ArrayUtils.toString( b.toArray( ) ) );
System.out.println( "Union: " + ArrayUtils.toString( union.toArray( ) ) );
System.out.println( "Intersection: " + 
                    ArrayUtils.toString( intersection.toArray( ) ) );
System.out.println( "Disjunction: " + 
                    ArrayUtils.toString( disjunction.toArray( ) ) );
System.out.println( "Subtract: " + ArrayUtils.toString( subtract.toArray( ) ) );


The previous example performs these four operations on two List objects, a and b, printing the results with ArrayUtils.toString( ):

A: {1,2,2,2,3,3,4,5}
B: {3,4,4,5,6,7}
Union: {1,2,2,2,3,3,4,4,5,6,7}
Intersection: {3,4,5}
Disjunction: {1,2,2,2,3,4,6,7}
Subtract: {1,2,2,2,3}

3 楼 tomkoo 2007-10-12  
Comparable实现排序,比较时还是需要循环啊
2 楼 kidd3166 2007-10-12  
你这样属于自定义对象集合,我曾经用过比较器来比较2个集合
上网查找一个关于Comparable,Comparator 的资料吧
1 楼 lovegiggs 2007-10-12  
可以考虑利用数据库资源来比较,写个存储过程来实现,通过内存来跑

对于存在差别的记录加上标记,然后就可一通过简单查询就可以得到

账单的平衡与否。

相关推荐

    SqlServer常用的几种分页查询SQL语句介绍、对比以及在.Net下的使用

    在性能方面,根据给出的数据,Offset Fetch表现最佳,平均查询时间最短,然后是ROW_NUMBER()开窗函数,而Top + 嵌套查询的效率最低。这主要是因为Offset Fetch和ROW_NUMBER()直接处理分页,而Top + 嵌套查询需要两次...

    cpp-benchmarkGoogle提供小型微基准测试支持库

    通过这些功能,开发者可以对比不同实现方案的性能,从而选择最佳实践。 **使用方法** 1. **安装与集成**: `google-benchmark`通常可以通过包管理器(如`vcpkg`、`conan`或`cmake`)轻松添加到项目中。首先,你需要...

    lambdas-and-streams-exercises-for-oracle-mooc:JDK 8 Lambdas和Streams Oracle MOOC的练习

    5. **反思总结**:完成练习后,回顾整个过程,思考如何优化代码,提高效率。 通过这样的练习,你可以逐步提升使用Lambda和Stream API的技能,更好地适应Java 8及更高版本的编程方式。在实践中学习,是掌握任何技术...

    数分1.11Tableau安装及使用教程

    数分1.11Tableau安装及使用教程

    软考信息系统运行管理员:涵盖信息系统运维、安全、架构及技术标准的多维考核

    内容概要:本文主要围绕着计算机信息系统运行管理员考试展开讨论,详细介绍了有关信息系统在运维中的各种问题及其应对方案。具体而言,文中不仅列举出了不同类型的信息系统对其本身的要求,而且还深入探讨了运维管理中面临的挑战和技术手段。另外,文章特别提及了一些特定类型的系统(例如政府系统和财务管理等),并指明在面对它们时需要考虑的安全级别、稳定性等关键要素;同时也强调了良好的文档管理和合理的设施运维对象划分,以及软硬件的选择与维护。同时文章还讲解了多种工具的作用(比如Nagios),以及硬件如计算机机房和UPS的具体规格和要求;并且讲述了关于变更管理和发布管理等的概念与实际应用场景。此外,在最后一部分内容里也谈到了云架构及其各个构成部分。 适用人群:本文适合即将参加软考信息运行管理员认证的专业人士,也适用于希望深入了解信息系统运作、管理和维护的技术从业者和相关领域的管理人员。 使用场景及目标:本资料旨在辅助考生掌握信息系统的高效、稳健地构建与运营所需的知识和技术,帮助他们顺利通过软考的同时提升实战经验;同时也为企业信息化建设提供了宝贵的理论基础和实践指南。 其他说明:虽然本文聚焦于特定职业资格证书

    伪知识图谱:元路径引导检索与图内文本技术,助力RAG增强型LLM

    大型语言模型(LLMs)的出现彻底改变了自然语言处理。然而,这些模型在从大量数据集中检索精确信息时面临挑战。检索增强生成(RAG)旨在通过结合外部信息检索系统来增强LLMs,从而提高响应的准确性和上下文性。尽管有所改进,RAG在高容量、低信息密度数据库中的全面检索仍然存在困难,并且缺乏关系意识,导致答案碎片化。 为了解决这一问题,本文介绍了伪知识图谱(PKG)框架,该框架通过集成元路径检索、图内文本和向量检索到LLMs中,旨在克服这些限制。通过保留自然语言文本并利用各种检索技术,PKG提供了更丰富的知识表示并提高了信息检索的准确性。使用Open Compass和MultiHop-RAG基准进行的广泛评估表明,该框架在管理和处理大量数据及复杂关系方面具有有效性。

    zedr_clean-code-python_1741402803.zip

    python学习教程

    kibana-7.10.2 docker镜像压缩包,百度网盘

    请到网盘中自取压缩包,此包为kibana-7.10.2 镜像压缩包,是通过现有镜像导出来的,主要是为了解决有些机器无法连接外网,导致无法下载镜像 加载镜像: docker load -i kibana-7.10.2.tar 查看镜像: docker images 备注:elk此镜像配套资源,相同版本的elasticsearch和logstash,请在我的资源中搜索其他镜像

    UniApp开发一个简单的记事本应用文字教程

    UniApp开发一个简单的记事本应用文字教程

    基于Andorid的音乐播放器项目设计(QQ音乐).zip

    基于Andorid的音乐播放器项目设计(QQ音乐)实现源码,主要针对计算机相关专业的正在做毕设的学生和需要项目实战练习的学习者,也可作为课程设计、期末大作业。

    编程语言_Python_Cookbook_管理工具_1741398354.zip

    python学习资源

    React Developer Tools在谷歌拓展的应用商城下载不了任何解决

    React Developer Tools在谷歌拓展的应用商城下载不了任何解决

    【毕业设计-java】springboot-vue健身房管理系统源码(完整前后端+mysql+说明文档+LunW).zip

    【毕业设计-java】springboot-vue健身房管理系统源码(完整前后端+mysql+说明文档+LunW).zip

    网络通信_批量IP管理_远程命令执行_工具_1741401998.zip

    python学习资源

    在Anaconda中创建和配置PyTorch环境的详细步骤

    本文提供了一套完整的指南,帮助用户在Anaconda中配置PyTorch环境,便于深度学习开发。首先,用户需要确保安装Anaconda,并通过Anaconda Prompt创建一个新的虚拟环境,以隔离项目依赖。创建好环境后,用户可以根据所用操作系统以及CUDA版本,选择适合的安装命令。对于Windows和Linux用户,提供了安装PyTorch、TorchVision和TorchAudio的具体命令,包括CUDA Toolkit的版本选择。macOS用户则可以安装仅支持CPU的版本。安装完成后,通过简单的Python代码验证PyTorch是否成功安装以及GPU的可用性。文中还列出了常见问题及解决方法,帮助用户快速排查安装过程中可能遇到的障碍。通过遵循这些步骤,用户可以顺利搭建起一个专属的PyTorch开发环境,提升深度学习的工作效率和体验。

    药品同步线程池模式_自动超时退出机制_1741403804.zip

    python学习教程

    数据结构学习指南:从资源到实战全方位提升编程技能

    内容概要:本文汇总了学习数据结构的相关资源,旨在帮助读者系统化地理解和掌握这一计算机科学的基础概念。文中首先列举了一系列权威在线学习资源,包括知名教授的主页、在线编程平台LeetCode和技术博客,这些资源不仅理论丰富,还提供大量的实例和练习机会。接着推荐了几本经典的书籍,如《算法导论》、《大话数据结构》,适合不同程度的学习者深入理解算法和数据结构的细节。此外,还特别提及了几门高质量的网络课程,能够为初学者提供清晰的学习路径。最后强调通过动手实践,如动态数组的C语言实现以及算法题目的刷题练习,是提高编程技能的有效途径。 适合人群:对于想要系统学习并掌握数据结构的程序员及爱好者。 使用场景及目标:适用于个人自学或者课堂教学,目的是通过综合使用理论学习、实践操作来达到对数据结构和算法有全面深刻的认识。 其他说明:本文提供了丰富的链接,让读者可以直接访问各个优质教育资源进行深度探究,鼓励大家积极参与讨论,相互分享心得体验,形成良好的互动交流氛围。

    QMI8658 Datasheet

    QMI8658 Datasheet

    【毕业设计】java-springboot-vue火车订票管理系统源码(完整前后端+mysql+说明文档+LunW).zip

    【毕业设计】java-springboot-vue火车订票管理系统源码(完整前后端+mysql+说明文档+LunW).zip

Global site tag (gtag.js) - Google Analytics