Java编程经验 您所在的位置:网站首页 java列表list Java编程经验

Java编程经验

2023-10-10 01:23| 来源: 网络整理| 查看: 265

Java编程经验---比较两个List对象差异 问题引入解决问题简化模型一般的办法速度更快的方法Lambda表达式解决办法 结语

问题引入

如何比较两个List对象的差异,这个问题来源于我最近正在开发的新系统中的一个细节。大致情况就是,从数据库中的一个视图A向另一个数据库的一张B表进行数据迁移。A的数据会随时更新,为了保证表B也可以及时获取数据,需要采用定时任务,不断同步数据。

每N分钟 视图A 表B

视图A中的数据在导入表B时,可能有数据已经在表B中,重复的导入浪费性能且可能发生潜在错误。那么就需要分析数据的差异后进行导入。先设一个前提,视图A与表B的结构相似,Primary Key为表中的某一单字段。

视图A示例

UserIdUserNameStatus…1MikeOK…2TrumpNO…3LiLiOK…

表B示例

UserIdUserNameGender…1MikeMen…2TrumpWomen…5ChouMen…

*这里的 UserId 时 Primery Key

解决问题 简化模型

我们可以先将问题简化为两个基本类型的List,举个最简单的例子就是两个List。

一般的办法

如何对比两个List的差异,最简单粗暴的当然就是使用两个for循环。

public static void main(String[] args) { int i = 0 ; //对比ListA和ListB的差异 List ListA = new LinkedList(); List ListB = new LinkedList(); //获取相同的元素放入ListC List ListC = new LinkedList(); while( i ListB.add(i); i++; } //程序开始时间 long st = System.nanoTime(); //取得相同的元素 for(int aIndex: ListA) { for(int bIndex: ListB) { if(aIndex == bIndex) { ListC.add(aIndex); } } } //分辨结束 System.out.println("total times "+(System.nanoTime()-st)); ListA.removeAll(ListC); ListB.removeAll(ListC); ListA.addAll(ListB); System.out.println(ListA.toString()); //打印差异元素 }

结果

total times 362768500 [0, 1, 2, 3, 4, 10000, 10001, 10002, 10003, 10004]

此时的算法复杂度为 O ( m × n ) O(m×n) O(m×n)

速度更快的方法

空间换时间

public class Test { public static void main(String[] args) { int i = 0 ; //对比ListA和ListB的差异 List ListA = new LinkedList(); List ListB = new LinkedList(); //获取相同的元素放入ListC List ListC = new LinkedList(); while( i ListB.add(i); i++; } Map listMap = new HashMap(); //程序开始时间 long st = System.nanoTime(); //取得相同的元素 Iterator iteratorA = ListA.iterator(); while(iteratorA.hasNext()) { Integer tempInteger = iteratorA.next(); listMap.put(tempInteger.intValue(),tempInteger); } Iterator iteratorB = ListB.iterator(); while(iteratorB.hasNext()) { Integer tempInteger = iteratorB.next(); if(listMap.containsKey(tempInteger)) { ListC.add(tempInteger); } } //分辨结束 System.out.println("total times "+(System.nanoTime()-st)); ListA.removeAll(ListC); ListB.removeAll(ListC); ListA.addAll(ListB); System.out.println(ListA.toString()); //打印差异元素 } }

结果

total times 2537200 [0, 1, 2, 3, 4, 10000, 10001, 10002, 10003, 10004]

做了一点改善,将原来的For循环用迭代来完成遍历,速度快了20%

此时的算法复杂度为 O ( m + n ) O(m+n) O(m+n) 很明显引入HashMap之后,算法复杂度大幅下降。这是由于在HashMap中查找元素的算法复杂度可以达到恐怖的O(1)。

特别说明 Java 8 之后,HashMap引入了红黑树存储,使得存储效率进一步提升,触发条件就是List长度大于8。

Lambda表达式解决办法 public static void main(String[] args) { int i = 0 ; //对比ListA和ListB的差异 List ListA = new ArrayList(); List ListB = new ArrayList(); //获取相同的元素放入ListC List ListC = new ArrayList(); while( i ListB.add(i); i++; } //程序开始时间 long st = System.nanoTime(); //取得相同的元素 //采用Lambda表达式实现 ListC = ListA.stream().filter(p -> ListB.contains((Integer)p)).collect(Collectors.toList()); //分辨结束 System.out.println("total times "+(System.nanoTime()-st)); ListA.removeAll(ListC); ListB.removeAll(ListC); ListA.addAll(ListB); System.out.println(ListA.toString()); //打印差异元素 }

先放结果吧

total times 41008300 [0, 1, 2, 3, 4, 10000, 10001, 10002, 10003, 10004]

总的来说还是要比第一种方法要快5,6倍,但是和使用HashMap还是有一定的差距。但是很明显语句非常的简洁。所以适当使用Lambda表达式可以使代码更加优雅。但是处理大量的数据时,效率不佳,不推荐。

结语

点滴积累,才能扎实成长。

时间有限,如有问题,及时更正。



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有