有关《查找两个List中的不同元素》的问题解答与编程实践
问题:
有List<String> list1和List<String> list2,两个集合各有上万个元素,怎样查找两个集合中不同的元素呢?
问题分析:
由于每个list中都有上万个元素,如果用简单的遍历查找算法,那么至少需要10000*10000次判断比较。显然,这样做的效率极低。那么有没有比较好的方案呢?经过我的思考,想出了2个办法。请大家评判。
方法一:遍历算法的改进算法
思路:对每一个list1中的元素,都在list2中查找一下,是否重复,如果不重复,则将该元素放到listDiff中。如果重复,则将该元素从list2中剔除。这样,能够减少遍历算法的时间复杂度,而且重复元素越多,该改进算法的运行时间就越短。当然,如果两个list的重复元素个数远远小于list的长度,则该算法的时间复杂度和遍历算法近似相同,会变的很慢而不切实际。
方法二:利用Map中无重复元素的特性
思路:将list1中元素首先复制到map<String,Integer>中,并将其Integer的值设置为1.然后再对list2中的元素,与map中元素比较。如果map中已经存在该String,那么map中对应String的Integer加1(表示字符串出现的次数),如果map中不存在,那么就将其复制到map中,并设置其Integer为1.那么,map中Integer值为1的元素所对应的String,就是两个list中不同的元素。
以下代码是在Java中实现,也可以用C++ STL进行测试。
- import java.util.ArrayList;
- import java.util.HashMap;
- import java.util.List;
- import java.util.Map;
- /*
- *@author: ZhengHaibo
- *2013-07-08 Nanjing,Conris,China
- */
- public class TestMian {
- private static final int ListLen = 10000;// 设置list的长度
- private static final Integer flagUnique = 1;//无重复字符串的键值
- public List<String> list1 = new ArrayList<String>();
- public List<String> list2 = new ArrayList<String>();
- public static void main(String[] args) {
- // TODO Auto-generated method stub
- TestMian mTest=new TestMian();
- mTest.initList();
- List<String> listDiff1=mTest.getDiffElementUseEach(mTest.list1,mTest.list2);//获得不同元素
- mTest.initList();
- List<String> listDiff2=mTest.getDiffElementUseMap(mTest.list1,mTest.list2);//获得不同元素
- System.out.println("The number of diff element is: "+listDiff1.size());
- System.out.println("The number of diff element is: "+listDiff2.size());
- //mTest.printList(listDiff1);
- //mTest.printList(listDiff2);
- }
- // 初始化list中的元素,并保证有相同的元素
- public void initList() {
- list1.clear();
- list2.clear();
- for (int i = 0; i < ListLen; i++) {
- list1.add("conris_list_of" + i + "test");
- list2.add("conris_list_of" + 3 * i + "test");
- }
- }
- //获得连个list中的不同元素,查找删除法
- public List<String> getDiffElementUseEach(List<String> list1,List<String> list2) {
- System.out.println("-----------------------方法1----------------------");
- long runtime = System.nanoTime();// 开始计时
- List<String> diffList = new ArrayList<String>();// 用于保存两个list中不同的元素
- for (String string:list1) {//消除list1本身的重复元素
- int index=list2.indexOf(string);
- if (index==-1) {//说明list2中不存在此元素
- diffList.add(string);
- }else{//list2存在此元素,那么删除此元素
- list2.remove(index);
- }
- }
- for(String string:list2){//此时,liat2中的重复元素已经删除了,只需要复制到diffList中即可
- diffList.add(string);
- }
- System.out.println("getDiffElementUseRemove run time:"
- + (System.nanoTime() - runtime));
- return diffList;
- }
- //获得两个list中的不同元素,map方法
- public List<String> getDiffElementUseMap(List<String> list1,List<String> list2){
- System.out.println("-----------------------方法2----------------------");
- long runtime = System.nanoTime();//开始计时
- //利用map中不能有重复元素的特点
- Map<String, Integer> map = new HashMap<String,Integer>(list1.size()+ list2.size());
- List<String> diffList = new ArrayList<String>();//用于保存两个list中不同的元素
- for (String string : list1) {
- map.put(string,flagUnique);//先将list1中元素复制到map中保存
- }
- for (String string : list2) {
- Integer key = map.get(string);// 获得键值
- if (key != null) {//如果map中已经存在该元素,说明list1中存在该元素,那么将其key加1
- map.put(string, ++key);
- continue;
- }else{//如果不存在,则放入map中
- map.put(string,flagUnique);
- }
- }
- for (Map.Entry<String, Integer> entry : map.entrySet()){
- if (entry.getValue() == flagUnique)//在map中,键值为flagUnique的元素即为无重复的元素
- {
- diffList.add(entry.getKey());
- }
- }
- System.out.println("getDiffElementUseMap run time:"
- + (System.nanoTime() - runtime));
- return diffList;
- }
- public void printList(List<String> list){
- for(int i=0;i<list.size();i++){
- System.out.println(list.get(i));
- }
- }
- }
实验结果:
当ListLen设置为10000时:
结果1:
- -----------------------方法1----------------------
- getDiffElementUseRemove run time:2015792051
- -----------------------方法2----------------------
- getDiffElementUseMap run time:37966034
- The number of diff element is: 13332
- The number of diff element is: 13332
当ListLen设置为100000时:等了半天方法1没有运行出来结果,方法2的运行结果如下:
- -----------------------方法2----------------------
- getDiffElementUseMap run time:471017640
- The number of diff element is: 133332
可见当数据量达到100000时(增大10倍),方法二仍然可以工作,而且时间也随着数据量增大线性增加。
而方法1很久也没有运行出来结果…
由此可见,利用HashMap的方法速度更快,能够满足基本要求。不知道大家还有哪些想法可以交流交流。希望对大家有帮助。
PS:如果用C++ STL实现的话,运行速度将更快!没事的时候再试试~~
有关《查找两个List中的不同元素》的问题解答与编程实践的更多相关文章
- Java - Collection 高效的找出两个List中的不同元素
如题:有List<String> list1和List<String> list2,两个集合各有上万个元素,怎样取出两个集合中不同的元素? 方法1:遍历两个集合 public ...
- php获取两个数组相同的元素(交集)以及比较两个数组中不同的元素(差集)
(一)php获取两个数组相同元素 array array_intersect(array $array1, array $array2, [, array $...]) array array_ ...
- Java Collection - 003 高效的找出两个List中的不同元素
如题:有List<String> list1和List<String> list2,两个集合各有上万个元素,怎样取出两个集合中不同的元素? 方法1:遍历两个集合 public ...
- HashMap通过hashcode对其内容进行快速查找,而 TreeMap中所有的元素都保持着某种固定的顺序
HashMap通过hashcode对其内容进行快速查找,而 TreeMap中所有的元素都保持着某种固定的顺序,如果你需要得到一个有序的结果你就应该使用TreeMap(HashMap中元素的排列顺序是不 ...
- C语言:返回两个数组中第一个元素的指针,并输出这个值
// // main.c // Pointer_search // // Created by ma c on 15/8/2. // Copyright (c) 2015年. All righ ...
- 寻找两个数组中的公共元素Java程序代码
package lianxi; import java.util.*; public class UnionSearch { public static void main(String[] args ...
- 获取两个List中的不同元素,4种方法,逐步优化,学习使用
完全复制https://www.cnblogs.com/czpblog/archive/2012/08/06/2625794.html 先上测试结果 代码 package com.syl.test; ...
- 遍历查找集合或者数组中的某个元素的值 java代码 详解 Android开发
import java.util.Scanner; public class Test21 { public static void main(String[] args) { //定义并初始化数组 ...
- 高效的找出两个List中的不同元素
/* * TestList.java * Version 1.0.0 * Created on 2017年12月15日 * Copyright ReYo.Cn */ package reyo.sdk. ...
随机推荐
- ArrayList、Vector和LinkedList
List接口特点 1.有序的 collection. 2.可以对列表中每个元素的插入位置进行精确地控制. 3.可以根据元素的索引访问元素,并搜索列表中的元素. 4.列表通常允许重复的元素. 5.允许存 ...
- Nexus-vPC和STP BPDU
1.为了交互vPC拓扑,STP机制被修改适应到vPC peer环境.2.对于vPC ports,只有主角色运行STP,换句话说,vPC下的STP由主角色设备控制.3.只有主角色设备在DP(指定端口)上 ...
- Update(Stage4):spark_rdd算子:第1节 RDD_定义_转换算子:深入RDD
一. 二.案例:详见代码.针对案例提出的6个问题: 假设要针对整个网站的历史数据进行处理, 量有 1T, 如何处理? 放在集群中, 利用集群多台计算机来并行处理 如何放在集群中运行? 简单来讲, 并行 ...
- Jquery实现ajax常用属性
- 01-JAVA语言基础(动手动脑)
一.一个JAVA类文件中只能有一个public类吗? 01-JAVA语言基础.ppt第22页“一个Java源文件中可以写多个类,但其中只能有一个类是“公有(public)”的,并且Java要求源文件名 ...
- 解决IDEA部署web项目时,jar包拷贝不全的问题
原因 先前已部署过,输出目录有lib文件夹. 再次部署时,IDEA一检测,发现输出目录已经存在lib文件夹,认为已经拷贝过了,为节省时间,不再重新拷贝jar包,殊不知我们新添加了jar包. 于是我们新 ...
- leetCode练题——12. Integer to Roman
1.题目 12. Integer to Roman Roman numerals are represented by seven different symbols: I, V, X, L, C, ...
- 【代码总结】PHP文件的上传和下载
===================== 文件上传和下载 ===================== 一.php.ini的配置信息 file_uploads = On /Off 是否允许文件上 ...
- 【转】路由转发过程的IP及MAC地址变化
A-----(B1-B2)-----(C1-C2)-------E 就假设拓扑图是这个样子吧,B1和B2是路由器B上的两个接口,C1和C2是路由器C上的两个接口,A和E是PC,由主机A向主机E发送数据 ...
- MNIST手写数字分类simple版(03-2)
simple版本nn模型 训练手写数字处理 MNIST_data数据 百度网盘链接:https://pan.baidu.com/s/19lhmrts-vz0-w5wv2A97gg 提取码:cgnx ...