开发者

Java使用Stream流的Lambda语法进行List转Map的操作方式

目录
  • 背景
  • Stream流的Lambda语法应用实例
    • 1、定义要操作的UserDto
    • 2、List编程客栈转成Map
      • List《UserDto》转成Map《String, UserDto》
      • List《UserDto》转成Map《String, Map《String, Object》》
      • List《UserDto》转Map《String, String》
      • List《Map《String, Object》》转Map《String, UserDto》
      • List《Map《String, Object》》转Map《String, String》
      • List《Map《String, Object》》转Map《String, Map《String, Object》》
      • List《Map》转Map《String, List《Map》》
  • 性能说明
    • 总结

      注:标题的<>被替换成了《》,标题带有<>会因为Bug被吞。

      背景

      在平时开发过程中难免会碰到有些时候需要将一个List转成Map又或者是将Map转成List,我们可以采用粗暴的方式来进行转换,但这样一是不够优雅,二是数据过多的时候性能不是很高。

      Lambda如果平时经常使用就可以知道这种语法糖有多方便使用,可以让代码变得十分简洁,而本篇便是用来说明使用Stream流的Lambda语法来优雅的进行List和Map的互转操作,并分析其性能差异。

      一些简单的便不做分析了,比如map()、peek()、filter()等方法,主要着重分析collect()的toMap()方法。

      Stream流的Lambda语法应用实例

      1、定义要操作的UserDto

      先定义一个UserDto以便直接后续使用,其代码如下:

      public class UserDto {
          private String name;
          private String sex;
          private String job;
          @Override
          public String toString() {
              return "{\"name\":\"" + name +
                      "\",\"sex\":\"" + sex +
                      "\",\"job\":\"" + job + "\"}";
          
          }
          // 后面其它的属性和getter、setter方法都忽略
      }

      2、List转成Map

      List转成Map有很多方式,使用foreach的方式什么转换都可以完成,但在本篇将会分享几个遍历的操作。

      List《UserDto》转成Map《String, UserDto》

      首先分享一下最简单的转换:

      由List<UserDto>转成以UserDto的name当成Key,而UserDto当成Value的Map操作,即Map<String, UserDto>形式。

      代码如下:

      public class MainTest {
          public static void main(String[] args) {
              UserDto userDto1 = new UserDto("test1", "man", "worker1");
              UserDto userDto2 = new UserDto("test2", "woman", "worker2");
              UserDto userDto3 = new UserDto("test3", "woman", "worker2");
              UserDto userDto4 = new UserDto("test4", "man", "worker3");
              List<UserDto> userList = Arrays
                  .asList(userDto1, userDto2, userDto3, userDto4);
              System.out.println(userList);
              // 使用stream流将List转成Map
              Map<String, UserDto> userMap = userList.stream()
                  .collect(Collectors.toMap(UserDto::getName, dto2 -> dto2));
              System.out.println(userMap);
          }
      }
      -------------打印结果-------------
      [{"name":"test1","sex":"man","job":"worker1"}, {"namhttp://www.devze.come":"test2","sex":"woman","job":"worker2"}, 
      {"name":"test3","sex":"woman","job":"worker2"}, {"name":"test4","sex":"man","job":"worker3"}]
      
      
      {test4={"name":"test4","sex":"man","job":"worker3"},test2={"name":"test2","sex":"woman","job":"worker2"}, 
      test3={"name":"test3","sex":"woman","job":"worker2"},test1={"name":"test1http://www.devze.com","sex":"man","job":"worker1"}}

      List《UserDto》转成Map《String, Map《String, Object》》

      接下来分享下将List<UserDto>转成Map<String, Map<String, Object>>形式的Lambda操作:

      public class MainTest {
          public static void main(String[] args) {
              UserDto userDto1 = new UserDto("test1", "man", "worker1");
              UserDto userDto2 = new UserDto("test2", "woman", "worker2");
              UserDto userDto3 = new UserDto("test3", "woman", "worker2");
              UserDto userDto4 = new UserDto("test4", "man", "worker3");
              List<UserDto> userList = Arrays
                  .asList(userDto1, userDto2, userDto3, userDto4);
              System.out.println(userList);
              // 使用stream流将List转成Map
              Map<String, Map<String, Object>> userMap = userList.stream()
              .collect(Collectors.toMap(UserDto::getName, dto2 ->
                      new HashMap<String, Object>(){{
                          put("name", dto2.getName());
                          put("sex", dto2.getSex());
                          put("job", dto2.getJob());}}));
              System.out.println(userMap);
          }
      }
      -------------打印结果-------------
      [{"name":"test1","sex":"man","job":"worker1"}, {"name":"test2","sex":"woman","job":"worker2"}, 
      {"name":"test3","sex":"woman","job":"worker2"}, {"name":"test4","sex":"man","job":"worker3"}]
      
      
      {test4={sex=man, name=test4, job=worker3}, test2={sex=woman, name=test2, job=worker2},
      test3={sex=woman, name=test3, job=worker2}, test1={sex=man, name=test1, job=worker1}}

      List《UserDto》转Map《String, String》

      接下来分享下将List<UserDto>转成Map<String, String>形式的Lambda操作,当然Map中String泛型也可以是Integer、Long甚至其它的类型,按照下面的方式进行相应的替换就行了:

      public class MainTest {
          public static void main(String[] args) {
              UserDto userDto1 = new UserDto("test1", "man", "worker1");
              UserDto userDto2 = new UserDto("test2", "woman", "worker2");
              UserDto userDto3 = new UserDto("test3", "woman", "worker2");
              UserDto userDto4 = new UserDto("test4", "man", "worker3");
              List<UserDto> userList = Arrays
                  .asList(userDto1, userDto2, userDto3, userDto4);
              System.out.println(userList);
              // 使用stream流将List转成Map
              Map<String, String> userMap = userList.stream()
              .collect(Collectors.toMap(UserDto::getName, UserDto::getSex));
              System.out.println(userMap);
          }
      }
      -------------打印结果-------------
      [{"name":"test1","sex":"man","job":"worker1"}, {"name":"test2","sex":"woman","job":"worker2"}, 
      {"name":"test3","sex":"woman","job":"worker2"}, {"name":"test4","sex":"man","job":"worker3"}]
      
      
      {test4=man, test2=woman, test3=woman, test1=man}

      List《Map《String, Object》》转Map《String, UserDto》

      由List<Map<String, Object>>转Map<String, UserDto>操作中,Map中的String也可以是Long、Integer或者其它的类型:

      public class MainTest {
          public static void main(String[] args) {
              Map<String, Object> userMap1 = new HashMap<String, Object>(8) {{
                  put("name", "test1");put("sex", "man");put("job", "worker1");
              }};
              Map<String, Object> userMap2 = new HashMap<String, Object>(8) {{
                  put("name", "test2");put("sex", "woman");put("job", "worker2");
              }};
              Map<String, Object> userMap3 = new HashMap<String, Object>(8) {{
                  put("name", "test3");put("sex", "woman");put("job", "worker2");
              }};
              Map<String, Object> userMap4 = new HashMap<String, Object>(8) {{
                  put("name", "test4");put("sex", "man");put("job", "worker3");
              }};
              List<Map<String, Object>> userList = Arrays.asList(userMap1, userMap2, userMap3, userMap4);
              System.out.println(userList);
              // 使用stream流将List转成Map
              Map<String, UserDto> userMap = userList.stream()
                      .collect(Collectors.toMap(map1 -> (String) map1.get("name"), map2 ->
                              new UserDto((String) map2.get("name"), (String) map2.get("sex"), (String) map2.get("job"))));
              System.out.println(userMap);
          }
      }
      -------------打印结果-------------
      [{name=test1, job=worker1, sex=man}, {name=test2, job=worker2, sex=woman}, 
      {name=test3, job=worker2, sex=woman}, {name=test4, job=worker3, sex=man}]
      
      
      {test4={"name":"test4","sex":"man","job":"worker3"}, test2={"name":"test2","sex":"woman","job":"worker2"}, 
      test3={"name":"test3","sex":"woman","job":"worker2"}, test1={"name":"test1","sex":"man","job":"worker1"}}

      List《Map《String, Object》》转Map《String, String》

      由List<Map<String, Object>>转Map<String, String>操作中,Map中的String也可以是Long、Integer或者其它的类型:

      public class MainTest {
          public static void main(String[] args) {
              Map<String, Object> userMap1 = new HashMap<String, Object>(8) {{
                  put("name", "test1");put("sex", "man");put("job", "worker1");
              }};
              Map<String, Object> userMap2 = new HashMap<String, Object>(8) {{
                  put("name", "test2");put("sex", "woman");put("job", "worker2");
              }};
              Map<String, Object> userMap3 = new HashMap<String, Object>(8) {{
                  put("name", "test3");put("sex", "woman");put("job", "worker2");
              }};
              Map<String, Object> userMap4 = new HashMap<String, Object>(8) {{
                  put("name", "test4");put("sex", "man");put("jobpython", "worker3");
              }};
              List<Map<String, Object>> userList = Arrays.asList(userMap1, userMap2, userMap3, userMap4);
              System.out.println(userList);
              // 使用stream流将List转成Map
              Map<String, String> userMap = userList.stream()
                      .collect(Collectors.toMap(map1 -> (String) map1.get("name"), 
                          map2 -> (String) map2.get("sex")));
              System.out.println(userMap);
          }
      }
      -------------打印结果-------------
      [{name=test1, job=worker1, sex=man}, {name=test2, job=worker2, sex=woman}, {name=test3, job=worker2, sex=woman}, {name=test4, job=worker3, sex=man}]
      
      {test4=man, test2=woman, test3=woman, test1=man}

      List《Map《String, Object》》转Map《String, Map《String, Object》》

      由List<Map<String, Object>>转Map<String, Map<String, Object>>操作中,Map中的String也可以是Long、Integer或者其它的类型:

      public class MainTest {
          public static void main(String[] args) {
              Map<String, Object> userMap1 = new HashMap<String, Object>(8) {{
                  put("name", "test1");put("sex", "man");put("job", "worker1");
              }};
              Map<String, Object> userMap2 = new HashMap<String, Object>(8) {{
                  put("name", "test2");put("sex", "woman");put("job", "worker2");
              }};
              Map<String, Object> userMap3 = new HashMap<String, Object>(8) {{
                  put("name", "test3");put("sex", "woman");put("job", "worker2");
              }};
              Map<String, Object> userMap4 = new HashMap<String, Object>(8) {{
                  put("name", "test4");put("sex", "man");put("job", "worker3");
              }};
              List<Map<String, Object>> userList = Arrays.asList(userMap1, userMap2, userMap3, userMap4);
              System.out.println(userList);
              // 使用stream流将List转成Map
              Map<String, Map<String, Object>> userMap = userList.stream()
              .collect(Collectors.toMap(map1 -> (String) map1.get("name"), map2 -> map2));
              System.out.println(userMap);
          }
      }
      -------------打印结果-------------
      [{name=test1, job=worker1, sex=man}, {name=test2, job=worker2, sex=woman}, 
      {name=test3, job=worker2, sex=woman}, {name=test4, job=worker3, sex=man}]
      
      
      {test4={name=test4, job=worker3, sex=man}, test2={name=test2, job=worker2, sex=woman},
      test3={name=test3, job=worker2, sex=woman}, test1={name=test1, job=worker1, sex=man}}

      List《Map》转Map《String, List《Map》》

      由List转Map>,根据Map中的某个值进行分组:

      public class MainTest {
          public static void main(String[] args) {
              Map<String, Object> userMap1 = new HashMap<String, Object>(8) {{
                  put("name", "test1");put("sex", "man");put("job", "worker1");
              }};
              Map<String, Object> userMap2 = new HashMap<String, Object>(8) {{
                  put("name", "test2");put("sex", "woman");put("job", "worker2");
              }};
              Map<String, Object> userMap3 = new HashMap<String, Object>(8) {{
                  put("name", "test3");put("sex", "woman");put("job", "worker2");
              }};
              Map<String, Object> userMap4 = new HashMap<String, Object>(8) {{
                  put("name", "test4");put("sex", "man");put("job", "worker3");
              }};
              List<Map<String, Object>> userList = Arrays.asList(userMap1, userMap2, userMap3, userMap4);
              System.out.println(userList);
              // 使用stream流将List转成Map
              Map<String, List<Map<String, Object>>> userMap = userList.stream()
                      .collect(Collectors.groupingBy(map1 -> (String) map1.编程客栈get("sex")));
              System.out.println(userMap);
          }
      }
      -------------打印结果-------------
      [{name=test1, job=worker1, sex=man}, {name=test2, job=worker2, sex=woman}, {name=test3, job=worker2, sex=woman}, {name=test4, job=worker3, sex=man}]
      {woman=[{name=test2, job=worker2, sex=woman}, {name=test3, job=worker2, sex=woman}], man=[{name=test1, job=worker1, sex=man}, {name=test4, job=worker3, sex=man}]}

      性能说明

      需要注意的是Stream使用流处理也是有使用限制的,比如初始化时间和性能限制:

      • 初始化时间:系统第一次使用Stream流的时候初始化时间如果是1W数据以内的需要几十毫秒,如果是10W数据以内的初始化需要100毫秒左右,100W初始化需要1000毫秒左右,1000W初始化则需要2500毫秒左右,而foreach的初始化时间和后续的时间是差不多的;
      • 运行性能:数据量在1W级别以下的时间花费差不多,10W数据以内的Stream流比性能是foreach的1/2,100W数据以内的Stream流性能是foreach的3/5,而到了1000W数据量级下Stream又变成了foreach的一倍左右,foreach到了1000W数据量级下最开始运行时间还保持在1400毫秒左右,到了后面则跑到了6000毫秒甚至7000毫秒,不知道是不是因为GC导致的。

      因此使用Stream时适用于低数据量的情况,当数据量级在1W以下是Stream流和foreach都可以使用,性能差别不大;到了10W-100W时应该使用foreach性能更快;而到了1000W量级的情况下就该使用Stream或者其它的大数据解析框架了。

      使用上述方式的20次平均运行时间表(仅代表本机I5-8400 2.8Ghz-2.81Ghz的规格CPU运行效率):

      运行方式

      数据量级

      初始化时间(ms)

      初始化后的

      平均运行效率(ms)

      foreach

      1W

      38

      1

      stream流

      1W

      1

      1

      foreach

      10W

      28

      6

      stream流

      10W

      54

      12

      foreach

      100W

      139

      111

      stream流

      100W

      1300

      181

      foreach

      1000W

      2500

      3500

      stream流

      1000W

      1130

      6000

      总结

      以上为个人经验,希望能给大家一个参考,也希望大家多多支持编程客栈(www.devze.com)。

      0

      上一篇:

      下一篇:

      精彩评论

      暂无评论...
      验证码 换一张
      取 消

      最新开发

      开发排行榜