java map大量数据库_Java中List和Map的特性对两组大批量数据进行匹配

在项目中遇到一个问题:要将通过http方式发送过来的大批量数据(这个数据保守估计每次请求在10万条左右),要和数据库中的另一批数据(数据库中的记录1万条左右)进行匹配(匹配:指两组数据中的某几个字段值相等),匹配上的数据保存在数据库中,匹配不上的直接扔掉。或者说:有一个List strList,List 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循环次数的耗时测试,结果表明减少循环次数能大幅度提高处理速度

所以我们一般写代码,双循环匹配是N*M,数据量不大可以,数据量大了那就。。。

import java.util.ArrayList;

import java.util.HashMap;

import java.util.List;

import java.util.Map;

/**

* For循环测试

* @author 47Gamer

*

*/

public class ForTest {

public static void main(String[] args) {

ForTest test = new ForTest();

System.out.println("============开始=============");

//一亿次for循环

test.test1Yi();

//十一万次for循环

test.test11W();

//嵌套for循环匹配:10W*1W次for循环

test.testForAndFor();

//Map和List整理匹配:10W+1W次for循环

test.testMapAndList();

System.out.println("============结束=============");

}

/**

* 一亿次for循环

*/

private void test1Yi(){

long start = System.currentTimeMillis();

for (Integer i = 0; i < 100000000;i++) {

System.out.println(i);

}

long end = System.currentTimeMillis();

System.out.println("1亿次循环耗时:"+ (end - start) + "毫秒");

System.out.println("----------------------------");

}

/**

* 11万次for循环

*/

private void test11W(){

long start = System.currentTimeMillis();

for (Integer i = 0; i < 110000;i++) {

System.out.println(i);

}

long end = System.currentTimeMillis();

System.out.println("11W次循环耗时:"+ (end - start) + "毫秒");

System.out.println("----------------------------");

}

/**

* 嵌套for循环进行比较匹配

*/

private void testForAndFor(){

//构造一个10万个Person对象的list

List personList = new ArrayList();

for (int i = 0; i < 100000; i++) {

int j =10000;

personList.add(new Person((i%j) +"", "张三"+i));

}

//构造一个1万个String对象的list

List strList = new ArrayList();

for (int i = 0; i < 10000; i++) {

strList.add(i +"");

}

//嵌套for循环:10W*1W

long start = System.currentTimeMillis();

//保存匹配结果

List resultList = new ArrayList();

//遍历10W person的List

for (Person person : personList) {

//遍历1W str的List

for (String str : strList) {

if(person.getId().equals(str)){

resultList.add(person);

}

}

}

long end = System.currentTimeMillis();

System.out.println("reslutList.size:"+ resultList.size());

System.out.println("10W*1W次循环耗时:"+ (end - start) + "毫秒");

System.out.println("----------------------------");

}

/**

* 使用Map和List的特性进行匹配:

* Map为key-value结构,不能放重复数据

* List可以放重复数据

* 使用String型id做key,List做value

* 遍历List, map.get(String)则取出id == str 的List

*/

private void testMapAndList(){

//构造一个10万个Person对象的list

List personList = new ArrayList();

for (int i = 0; i < 100000; i++) {

int j =10000;

personList.add(new Person((i%j) +"", "张三"+i));

}

//构造一个1万个String对象的list

List strList = new ArrayList();

for (int i = 0; i < 10000; i++) {

strList.add(i +"");

}

long start = System.currentTimeMillis();

//利用Map和List的特性整理数据

Map> map = new HashMap>();

//将10W条数据根据id放入map

for(int i=0;i

Person person = personList.get(i);

String id = person.getId();

if(map.containsKey(id)){

map.get(id).add(person);

}else{

List pList = new ArrayList();

pList.add(person);

//id为key,相同id的person的List为value

map.put(id,pList);

}

}

//保存匹配结果

List resultList = new ArrayList();

//根据1W条str,map.get(str)取匹配上的数据

for (String str : strList) {

List pList = map.get(str);

if (pList != null) {

resultList.addAll(pList);

}

}

long end = System.currentTimeMillis();

System.out.println("map.size:" +map.size());

System.out.println("reslutList.size:"+ resultList.size());

System.out.println("10W+1W次循环耗时:"+ (end - start) + "毫秒");

System.out.println("----------------------------");

}

}

/**

* Person实体类

*/

class Person{

private String id;

private String name;

public Person() {}

public Person(String id, String name) {

this.id = id;

this.name = name;

}

@Override

public String toString() {

return this.id +"::>"+ this.name;

}

public String getId() {

return id;

}

public void setId(String id) {

this.id = id;

}

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

}

测试结果:

============开始=============

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多陪,达到了预想的目的。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值