两个List循环效率对比 List转Map 循环效率对比 Listmap 循环 效率对比

一、情景描述

        1、在微服务开发中,如: 查询用户列表 userList,需要关联查询 每个用户下面的文件信息,由于数据库层隔离,不能直接进行 left join ,则需要通过关联查询 文件服务,来获取每个用户下的文件信息,伪代码如下:

List<User> userList = userService.getList(xx);
 
List<UserFile> userFileList = fileService.getList(userIdList);

        2、再通过 关联的id,进行匹配; 一般进行匹配的方式有2种,

同时遍历 userList 和 userFileList ,逐一匹配 ;
其中一个 userList 转换为 userListMap,然后遍历另外一个 userFileList ,再进行匹配
        3、本文将模拟以上2种情况,进行测试对比匹配的效率,用于总结后续的开发中,遇到类似的情况,该如何处理的,经验总结。

二、代码实现

        1、定义一个 普通的内部类,有3个属性:

static class User{
    private  Integer id ;
    private String name ;
    private Integer score ;
    // ingnore getter /setter construction
}

        2、初始化2个 list , 一个 1w数据,一个10w数据 

List<User> list = Lists.newArrayList();
List<User> list10 = Lists.newArrayList();
 
@Before
public void before() throws Exception {
    int n1 = 10_000;
    int n2 = 1_00_000;
    System.out.println("n1 ="+n1 +" ; n2="+n2);
 
    initList(n1);
    initList2(n2);
 
    System.out.println("初始化 list 完成 , list = "+ list.size() + " list10 = "+ list10.size());
}
 
private void initList(int n) {
    for (int i = 0; i < n; i++) {
        list.add(new User(i,"小明"+i));
    }
}
 
private void initList2(int n2) {
    for (int i = 0; i < n2; i++) {
        list10.add(new User(i,"小明"+i, new Random().nextInt()));
    }
}

       3、1w List 循环 10w List :

@Test
public void listCompare() throws Exception {
    final StopWatch stopWatch = StopWatch.createStarted();
    list.forEach(e->{
        list10.forEach(e2->{
            if(e.getId().equals(e2.getId())){
                e.setScore(e2.getScore());
            }
        });
    });
    System.out.println("测试匹配情况: list, 100=" + list.get(100).getScore()
            + " ; list10 , 100="+list10.get(100).getScore());
    stopWatch.stop();
    System.out.println("1w List 循环 10w List,耗时:" + stopWatch.getTime()+" ms");
}

        3.1、输出结果如下:

n1 =10000 ; n2=100000
初始化 list 完成 , list = 10000 list10 = 100000
测试匹配情况: list, 100=1980067001 ; list10 , 100=1980067001
1w List 循环 10w List,耗时:7370 ms

        4、10w List 循环 1w List

@Test
public void list10Compare() throws Exception {
    final StopWatch stopWatch = StopWatch.createStarted();
    list10.forEach(e->{
        list.forEach(e2->{
            if(e.getId().equals(e2.getId())){
                e2.setScore(e.getScore());
            }
        });
    });
    System.out.println("测试匹配情况: list, 100=" + list.get(100).getScore()
            + " ; list10 , 100="+list10.get(100).getScore());
    stopWatch.stop();
    System.out.println("10w List 循环 1w List,耗时:" + stopWatch.getTime()+" ms");
}

        4.1、输出结果如下:

n1 =10000 ; n2=100000
初始化 list 完成 , list = 10000 list10 = 100000
测试匹配情况: list, 100=-110042713 ; list10 , 100=-110042713
10w List 循环 1w List,耗时:1489 ms

        5、 1w List转Map 循环 10w List 对比:

@Test
public void listMapCompare() throws Exception {
    final StopWatch stopWatch = StopWatch.createStarted();
    final Map<Integer, User> map = list.stream().collect(Collectors.toMap(k -> k.getId(), v -> v));
    list10.forEach(e->{
        final User user = map.get(e.getId());
        if(Objects.nonNull(user)){
            user.setScore(e.getScore());
        }
    });
 
    System.out.println("测试匹配情况: list, 100=" + list.get(100).getScore()
            + " ; list10 , 100="+list10.get(100).getScore());
    stopWatch.stop();
    System.out.println("1w List转Map 循环 10w List 对比,耗时:" + stopWatch.getTime()+" ms");
}

        5.1、输出结果如下:

n1 =10000 ; n2=100000
初始化 list 完成 , list = 10000 list10 = 100000
测试匹配情况: list, 100=690010328 ; list10 , 100=690010328
1w List转Map 循环 10w List 对比,耗时:49 ms

        6、10w List转Map 循环 1w List 对比:

@Test
public void list10MapCompare() throws Exception {
    final StopWatch stopWatch = StopWatch.createStarted();
    final Map<Integer, User> map = list10.stream().collect(Collectors.toMap(k -> k.getId(), v -> v));
    list.forEach(e->{
        final User user = map.get(e.getId());
        if(Objects.nonNull(user)){
            e.setScore(user.getScore());
        }
    });
 
    System.out.println("测试匹配情况: list, 100=" + list.get(100).getScore()
            + " ; list10 , 100="+list10.get(100).getScore());
    stopWatch.stop();
    System.out.println("10w List转Map 循环 1w List 对比,耗时:" + stopWatch.getTime()+" ms");
}

        6.1、输出结果如下:

n1 =10000 ; n2=100000
初始化 list 完成 , list = 10000 list10 = 100000
测试匹配情况: list, 100=-623027169 ; list10 , 100=-623027169
10w List转Map 循环 1w List 对比,耗时:56 ms

三、总结

        1、2个list 循环的时候,转成一个为 map,再进行匹配,效率更高。

        2、2个循环同时执行时候: 大循环 套 小循环,效率更高 。【二-3 和 二-4】的执行效率对比;比如:循环 100w次, 10000*100 比 100*10000 效率会更高。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在进行两个List之间的对象换时,可以使用实体换类来实现。首先,你需要创建一个换类,例如UserTransform。在这个类中,你可以定义各种换方法来满足你的需求。比如,你可以在UserTransform类中定义一个方法booleanToString,用于将boolean类型的值换为字符串类型的值。另外,你还可以定义一个方法strToBoolean,用于将字符串类型的值换为boolean类型的值。\[3\] 接下来,在进行List换时,你需要遍历源List中的每个对象,并使用换类中定义的方法进行换。然后,将换后的对象添加到目标List中。这样,你就完成了两个List之间的对象换。\[2\] 请注意,在进行List换时,你需要确保属性名对应。如果属性名不对应,你可以在实体换方法中使用@Mappings注解进行属性名映射配置,以确保换的准确性。\[2\] 以下是一个示例代码,演示了如何进行两个List之间的对象换: ```java public class UserTransform { public String booleanToString(boolean value){ if(value){ return "男"; } return "女"; } public boolean strToBoolean(String str){ if ("男".equals(str)) { return true; } return false; } } public class Main { public static void main(String\[\] args) { List<User> userList = Arrays.asList( new User("张三", true), new User("李四", false) ); List<Student> studentList = new ArrayList<>(); UserTransform userTransform = new UserTransform(); for(User user : userList){ Student student = new Student(); student.setName(user.getName()); student.setGender(userTransform.booleanToString(user.isMale())); studentList.add(student); } // 输出换后的studentList for(Student student : studentList){ System.out.println(student.getName() + " - " + student.getGender()); } } } ``` 在上面的示例代码中,我们首先创建了一个UserTransform类,其中定义了booleanToString和strToBoolean两个换方法。然后,我们创建了一个User列表userList,并初始化了一些User对象。接下来,我们创建了一个空的Student列表studentList,并实例化了UserTransform类。 然后,我们使用for循环遍历userList中的每个User对象,并使用UserTransform类中的booleanToString方法将boolean类型的gender属性换为字符串类型。然后,我们将换后的对象添加到studentList中。 最后,我们使用for循环遍历studentList,并输出每个Student对象的name和gender属性,以验证换的准确性。 希望这个示例能帮助你理解如何进行两个List之间的对象换。如果你有任何其他问题,请随时提问。 #### 引用[.reference_title] - *1* [使用Stream对List、Set和Map的增强操作](https://blog.csdn.net/qq_41469636/article/details/107629289)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* *3* [mapstruct 实体换及List换](https://blog.csdn.net/sebeefe/article/details/126434948)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值