Java中List和Map的特性对两组大批量数据进行匹配 (转)

在项目中遇到一个问题:要将通过http方式发送过来的大批量数据(这个数据保守估计每次请求在10万条左右),要和数据库中的另一批数据(数据库中的记录1万条左右)进行匹配(匹配:指两组数据中的某几个字段值相等),匹配上的数据保存在数据库中,匹配不上的直接扔掉。或者说:有一个List<String> strList,List<Person> personList,strNoList.size是1万,personList.size是10万, 然后要从personList中把person的id属性在strList中的person取出来,personList中的person的id可能会相同,两个记录的结构不同。

要实现这个功能,首先想到的就是使用for循环逐条进行比较,那么这样就有10W*1W,即10亿次循环。但是,系统对数据的实时性要求比较高,这样做显然性能上是有问题的。于是乎就要找另一种方式,减少循环次数来提高匹配的处理速度,由于之前也没做个这样的事情,于是就想各种办法,同时在OSC社区发帖求助

List可以放重复数据,而Map为不能放重复数据的key-value结构。那么就可以把接收到的id相同的person实体数据放入一个list中,然后用该id作为key,list做作为value放入map中。那么现在处理10w条数据则需要10W次for循环。然后查出数据库中的1W条记录,遍历map,使用map.get("key")取出相同id的list,然后将这些list的元素全部添加到一个resultList中,遍历这1W条记录需要1W次for循环。这样,就将一个10W*1W次的for循环减小到10W+1W次。下边是关于for循环次数的耗时测试,结果表明减少循环次数能大幅度提高处理速度

  1 import java.util.ArrayList;
  2 import java.util.HashMap;
  3 import java.util.List;
  4 import java.util.Map;
  5 /**
  6  * For循环测试
  7  * @author 大漠
  8  *
  9  */
 10 public class ForTest {
 11  public static void main(String[] args) {
 12   ForTest test = new ForTest();
 13   System.out.println("============开始=============");
 14    //一亿次for循环
 15    test.test1Yi();
 16    //十一万次for循环
 17    test.test11W();
 18    //嵌套for循环匹配:10W*1W次for循环
 19    test.testForAndFor();
 20    //Map和List整理匹配:10W+1W次for循环
 21    test.testMapAndList();
 22   System.out.println("============结束=============");
 23  }
 24  /**
 25   * 一亿次for循环
 26   */
 27  private void test1Yi(){
 28   long start = System.currentTimeMillis();
 29   for (Integer i = 0; i < 100000000;i++) {
 30    System.out.println(i);
 31   }
 32   long end = System.currentTimeMillis();
 33   System.out.println("1亿次循环耗时:"+ (end - start) + "毫秒");
 34   System.out.println("----------------------------");
 35  }
 36
 37  /**
 38   * 11万次for循环
 39   */
 40  private void test11W(){
 41   long start = System.currentTimeMillis();
 42   for (Integer i = 0; i < 110000;i++) {
 43    System.out.println(i);
 44   }
 45   long end = System.currentTimeMillis();
 46   System.out.println("11W次循环耗时:"+ (end - start) + "毫秒");
 47   System.out.println("----------------------------");
 48  }
 49
 50  /**
 51   * 嵌套for循环进行比较匹配
 52   */
 53  private void  testForAndFor(){
 54   //构造一个10万个Person对象的list
 55   List<Person> personList = new ArrayList<Person>();
 56   for (int i = 0; i < 100000; i++) {
 57    int j =10000;
 58    personList.add(new Person((i%j) +"", "张三"+i));
 59   }
 60   //构造一个1万个String对象的list
 61   List<String> strList = new ArrayList<String>();
 62   for (int i = 0; i < 10000; i++) {
 63    strList.add(i +"");
 64   }
 65
 66   //嵌套for循环:10W*1W
 67   long start = System.currentTimeMillis();
 68   //保存匹配结果
 69         List<Person> resultList = new ArrayList<Person>();
 70         //遍历10W person的List
 71         for (Person person : personList) {
 72          //遍历1W str的List
 73             for (String str : strList) {
 74                 if(person.getId().equals(str)){
 75                     resultList.add(person);
 76                 }
 77             }
 78         }
 79         long end = System.currentTimeMillis();
 80         System.out.println("reslutList.size:"+ resultList.size());
 81         System.out.println("10W*1W次循环耗时:"+ (end - start) + "毫秒");
 82         System.out.println("----------------------------");
 83  }
 84
 85  /**
 86   * 使用Map和List的特性进行匹配:
 87   * Map为key-value结构,不能放重复数据
 88   * List可以放重复数据
 89   * 使用String型id做key,List<Person>做value
 90   * 遍历List<String>, map.get(String)则取出id == str 的List
 91   */
 92  private void  testMapAndList(){
 93   //构造一个10万个Person对象的list
 94   List<Person> personList = new ArrayList<Person>();
 95
 96   for (int i = 0; i < 100000; i++) {
 97    int j =10000;
 98    personList.add(new Person((i%j) +"", "张三"+i));
 99   }
100   //构造一个1万个String对象的list
101   List<String> strList = new ArrayList<String>();
102   for (int i = 0; i < 10000; i++) {
103    strList.add(i +"");
104   }
105
106   long start = System.currentTimeMillis();
107   //利用Map和List的特性整理数据
108         Map<String, List<Person>> map = new HashMap<String, List<Person>>();
109         //将10W条数据根据id放入map
110         for(int i=0;i<personList.size();i++){
111          Person person = personList.get(i);
112              String id = person.getId();
113               if(map.containsKey(id)){
114                   map.get(id).add(person);
115               }else{
116                    List<Person> pList = new ArrayList<Person>();
117                    pList.add(person);
118                    //id为key,相同id的person的List为value
119                    map.put(id,pList);
120              }
121         }
122       //保存匹配结果
123         List<Person> resultList = new ArrayList<Person>();
124         //根据1W条str,map.get(str)取匹配上的数据
125         for (String str : strList) {
126             List<Person> pList = map.get(str);
127             if (pList != null) {
128                 resultList.addAll(pList);
129             }
130         }
131         long end = System.currentTimeMillis();
132         System.out.println("map.size:" +map.size());
133         System.out.println("reslutList.size:"+ resultList.size());
134         System.out.println("10W+1W次循环耗时:"+ (end - start) + "毫秒");
135   System.out.println("----------------------------");
136  }
137 }
138 /**
139  * Person实体类
140  */
141 class Person{
142  private String id;
143  private String name;
144  public Person() {}
145
146  public Person(String id, String name) {
147   this.id = id;
148   this.name = name;
149  }
150  @Override
151  public String toString() {
152   return this.id +"::>"+ this.name;
153  }
154
155  public String getId() {
156   return id;
157  }
158  public void setId(String id) {
159   this.id = id;
160  }
161  public String getName() {
162   return name;
163  }
164  public void setName(String name) {
165   this.name = name;
166  }
167 }

测试结果:

============开始=============
1亿次循环耗时:1262985毫秒
----------------------------
11W次循环耗时:1016毫秒
----------------------------
reslutList.size:100000
10W*1W次循环耗时:21219毫秒
----------------------------
map.size:10000
reslutList.size:100000
10W+1W次循环耗时:31毫秒
============结束=============

•1亿次system.out.println(i)的循环耗时1262985毫秒,即21分钟,那么10亿次210分钟,显然不可接受。当然这里设计I/O操作,比较耗时,实际应用中没有这么吓人。
•11万次system.out.println(i)循环耗时1016毫秒,即1秒种,很明显,减少循环次数能够提高处理速度。
•使用嵌套for循环完成10W*1W次循环耗时21219毫秒,使用第二种方法完成10W+1W次循环耗时31毫秒,处理速度提高了600多陪,达到了预想的目的。

时间: 2024-10-12 03:54:02

Java中List和Map的特性对两组大批量数据进行匹配 (转)的相关文章

转!! Java中如何遍历Map对象的4种方法

在Java中如何遍历Map对象 How to Iterate Over a Map in Java 在java中遍历Map有不少的方法.我们看一下最常用的方法及其优缺点. 既然java中的所有map都实现了Map接口,以下方法适用于任何map实现(HashMap, TreeMap, LinkedHashMap, Hashtable, 等等) 方法一 在for-each循环中使用entries来遍历 这是最常见的并且在大多数情况下也是最可取的遍历方式.在键值都需要时使用. [java] view

JAVA中List、Map、Set的区别与选用

类层次关系如下: Collection ├List│├LinkedList│├ArrayList│└Vector│ └Stack└SetMap├Hashtable├HashMap └WeakHashMap 下面来分别介绍 Collection接口 Collection是最基本的集合接口,一个Collection代表一组Object,即Collection的元素(Elements).一些 Collection允许相同的元素而另一些不行.一些能排序而另一些不行.Java SDK不提供直接继承自Col

JAVA中,JSON MAP LIST的相互转换

1 JSON包含对象和数组,对应于JAVA中的JSONObject,JSONArray 2 String 转JSON对象 JSONObject.fromObject("String"); String 转JSON数组 JSONArray.fromObject("String"); 3 List 和 JSON互转 JSONObject.toBean() JSONArray.fromObject(List) JAVA中,JSON MAP LIST的相互转换,布布扣,bu

(转)在Java中如何遍历Map对象

在Java中如何遍历Map对象 How to Iterate Over a Map in Java 在java中遍历Map有不少的方法.我们看一下最常用的方法及其优缺点. 既然java中的所有map都实现了Map接口,以下方法适用于任何map实现(HashMap, TreeMap, LinkedHashMap, Hashtable, 等等) 方法一 在for-each循环中使用entries来遍历 这是最常见的并且在大多数情况下也是最可取的遍历方式.在键值都需要时使用. [java] view

(转载)Java中如何遍历Map对象的4种方法

在Java中如何遍历Map对象 How to Iterate Over a Map in Java 在java中遍历Map有不少的方法.我们看一下最常用的方法及其优缺点. 既然java中的所有map都实现了Map接口,以下方法适用于任何map实现(HashMap, TreeMap, LinkedHashMap, Hashtable, 等等) 方法一 在for-each循环中使用entries来遍历 这是最常见的并且在大多数情况下也是最可取的遍历方式.在键值都需要时使用. Map<Integer,

Java中如何遍历Map对象的4种方法

在Java中如何遍历Map对象 How to Iterate Over a Map in Java 在java中遍历Map有不少的方法.我们看一下最常用的方法及其优缺点. 既然java中的所有map都实现了Map接口,以下方法适用于任何map实现(HashMap, TreeMap, LinkedHashMap, Hashtable, 等等) 方法一 在for-each循环中使用entries来遍历 这是最常见的并且在大多数情况下也是最可取的遍历方式.在键值都需要时使用. [java] view

java中的三(四)大特性

java中的三(四)大特性 :继承 . 封装 .多态.(抽象) 类与类之间的关系: is-a                   继承 .实现 继承的表现:使用extends继承父类 实现的表现:使用importance实现接口 has-a                组合 .聚合.关联 关联的表现:关联关系一般使用成员变量来实现. use-a (need-a)  依赖 依赖的表现,一个类的方法操作另一个类的对象 例如:人(Person) 开 车(Car) 继承 使用extends关键词  子

java中List、Map、Set、Stack、Queue、Collections等的使用

java中List.Map.Set.Stack.Queue.Collections等的使用 List 创建方法: List<String> list=new ArrayList<>(); add(val) : 添加元素. get(index) : 获取元素. remove(index) : 删除元素. remove(Object o) : 按照元素内容删除 {eg:list.add("marry") ; list.remove(0)==list.remove(&

java中几种Map在什么情况下使用,并简单介绍原因及原理

一.Map用于保存具有映射关系的数据,Map里保存着两组数据:key和value,它们都可以使任何引用类型的数据,但key不能重复.所以通过指定的key就可以取出对应的value.Map接口定义了如下常用的方法:1.void clear():删除Map中所以键值对.2.boolean containsKey(Object key):查询Map中是否包含指定key,如果包含则返回true.3.boolean containsValue(Object value):查询Map中是否包含指定value