0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

List 转 Map的方法

科技绿洲 来源:Java技术指北 作者:Java技术指北 2023-10-09 16:10 次阅读

在我们平时的工作中,充满了各种类型之间的转换。今天小编带大家上手 List 转 Map 的各种操作。

我们将假设 List 中的每个元素都有一个标识符,该标识符将在生成的 Map 中作为一个键使用。

定义一个类型

我们在转换之前,我们先暂定一个类来用于各种转换demo的演示。

public class Animal {
    private int id;
    private String name;

    //  构造函数 、 get 、 set
}

我们假定 id 字段 是唯一的, 所以我们把 id 作为 Map 的key。

使用 Java 8 之前的方法

在使用Java 8 之前,就只能使用比较传统的for 循环来转换。

public Map< Integer, Animal > convertListBeforeJava8(List< Animal > list) {
    Map< Integer, Animal > map = new HashMap<  >();
    for (Animal animal : list) {
        map.put(animal.getId(), animal);
    }
    return map;
}

我们需要写一个测试代码,测试下是否正常运行了。

@Test
public void testConvertListBeforeJava8() {
    Map< Integer, Animal > map = convertListService
      .convertListBeforeJava8(list);
    
    assertThat(
      map.values(), 
      containsInAnyOrder(list.toArray()));
}

使用Java 8 stream

在Java 8 之后,我们可以通过新增的 Stream API 来进行转换操作

public Map< Integer, Animal > convertListAfterJava8(List< Animal > list) {
    Map< Integer, Animal > map = list.stream()
      .collect(Collectors.toMap(Animal::getId, Function.identity()));
    return map;
}

测试代码

@Test
public void testConvertListAfterJava8() {
    Map< Integer, Animal > map = convertListService.convertListAfterJava8(list);
    
    assertThat(
      map.values(), 
      containsInAnyOrder(list.toArray()));
}

使用Guava库

除了使用核心的Java API ,我们还能通过第三方库来实现这些操作。

使用Guava 库, 我们需要先引入依赖, 我们先在maven 中引入进来。

< !-- https://mvnrepository.com/artifact/com.google.guava/guava -- >
< dependency >
    < groupId >com.google.guava< /groupId >
    < artifactId >guava< /artifactId >
    < version >31.0.1-jre< /version >
< /dependency >

接下来使用 Maps.uniqueIndex() 进行转换

public Map< Integer, Animal > convertListWithGuava(List< Animal > list) {
    Map< Integer, Animal > map = Maps
      .uniqueIndex(list, Animal::getId);
    return map;
}

测试代码

@Test
public void testConvertListWithGuava() {
    Map< Integer, Animal > map = convertListService
      .convertListWithGuava(list);
    
    assertThat(
      map.values(), 
      containsInAnyOrder(list.toArray()));
}

使用 Apache Commons 库

除了 Guava ,我们还可以使用常用的 Apache Commons 库来进行转换。

我们现在Maven 中引入 commons 的依赖库

< !-- https://mvnrepository.com/artifact/org.apache.commons/commons-collections4 -- >
< dependency >
    < groupId >org.apache.commons< /groupId >
    < artifactId >commons-collections4< /artifactId >
    < version >4.4< /version >
< /dependency >

接下来我们使用 MapUtils.populateMap() 方法进行转换。

public Map< Integer, Animal > convertListWithApacheCommons2(List< Animal > list) {
    Map< Integer, Animal > map = new HashMap<  >();
    MapUtils.populateMap(map, list, Animal::getId);
    return map;
}

测试代码

@Test
public void testConvertListWithApacheCommons2() {
    Map< Integer, Animal > map = convertListService
      .convertListWithApacheCommons2(list);
    
    assertThat(
      map.values(), 
      containsInAnyOrder(list.toArray()));
}

Map Key 的冲突问题

由于List中可以存在多个相同的实例, 但是map却不行, 那我们来看看Map要怎么处理呢?

首先,我们初始化一个有重复对象的 List

@Before
public void init() {

    this.duplicatedIdList = new ArrayList<  >();

    Animal cat = new Animal(1, "Cat");
    duplicatedIdList.add(cat);
    Animal dog = new Animal(2, "Dog");
    duplicatedIdList.add(dog);
    Animal pig = new Animal(3, "Pig");
    duplicatedIdList.add(pig);
    Animal cow = new Animal(4, "牛");
    duplicatedIdList.add(cow);
    Animal goat= new Animal(4, "羊");
    duplicatedIdList.add(goat);
}

从代码中可以看到, 牛 和 羊 对象的id 都是 4 。

Apache Commons 和 Java 8 之前的代码是一样的,相同id的Map 在put 的时候会进行覆盖。

@Test
public void testConvertBeforeJava8() {

    Map< Integer, Animal > map = convertListService
      .convertListBeforeJava8(duplicatedIdList);

    assertThat(map.values(), hasSize(4));
    assertThat(map.values(), hasItem(duplicatedIdList.get(4)));
}

@Test
public void testConvertWithApacheCommons() {

    Map< Integer, Animal > map = convertListService
      .convertListWithApacheCommons(duplicatedIdList);

    assertThat(map.values(), hasSize(4));
    assertThat(map.values(), hasItem(duplicatedIdList.get(4)));
}

而 Java 8 的 Collectors.toMap() 和 Guava 的 MapUtils.populateMap() 分别抛出 IllegalStateException 和 IllegalArgumentException。

@Test(expected = IllegalStateException.class)
public void testGivenADupIdListConvertAfterJava8() {

    convertListService.convertListAfterJava8(duplicatedIdList);
}

@Test(expected = IllegalArgumentException.class)
public void testGivenADupIdListConvertWithGuava() {

    convertListService.convertListWithGuava(duplicatedIdList);
}

总结

在这篇文章中,指北君给大家分享了各种List 转 Map 的方法, 给出了使用 Java 原生API 以及一些流行的第三方库的例子。

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 函数
    +关注

    关注

    3

    文章

    4273

    浏览量

    62292
  • 代码
    +关注

    关注

    30

    文章

    4708

    浏览量

    68176
  • MAP
    MAP
    +关注

    关注

    0

    文章

    48

    浏览量

    15120
收藏 人收藏

    评论

    相关推荐

    OpenHarmony语言基础类库【@ohos.util.List (线性容器List)】

    List底层通过单向链表实现,每个节点有一个指向后一个元素的引用。当需要查询元素时,必须从头遍历,插入、删除效率高,查询效率低。List允许元素为null。
    的头像 发表于 05-10 16:57 669次阅读
    OpenHarmony语言基础类库【@ohos.util.<b class='flag-5'>List</b> (线性容器<b class='flag-5'>List</b>)】

    add_ready_list_end

    ], &task_ptr->task_list);bit_set(rq->task_bit_map, priority);/*update highest_priority
    发表于 06-08 17:26

    labview中 list 列表实时读取问题

    网上找了个程序,是关于 USBCAN的数据接收,但有些问题不明白。下图 1 中的list 空间并没放在while循环中,但该list控件能一直实时更新数据而list控件的程序框中的所
    发表于 09-05 10:19

    是否有指示MAP方法

    寄存器上的SRL。是否有指示MAP方法,它不应该在某些信号上推断SRL?谢谢杰夫以上来自于谷歌翻译以下为原文I have a design that has high clock rates.I
    发表于 10-10 10:52

    Map Service Engine Based On We

    Abstract:A design and implementation of map service engine based on web is introduced
    发表于 07-23 10:43 17次下载

    List of Equivalent Product

    List of Equivalent Product
    发表于 08-19 12:32 12次下载

    Allego中find by list使用方法

    Allego中find by list使用方法 先对每单张原理图出bom表! 然后把他其中的标号 r1,c1,u1之类的放在另一个文本中,注意不要用逗号隔开! 将文
    发表于 03-22 16:24 1463次阅读

    基于MAP+CMLLR的说话人识别中发声力度问题

    为了改善发声力度对说话人识别系统性能的影响,在训练语音存在少量耳语、高喊语音数据的前提下,提出了使用最大后验概率(MAP)和约束最大似然线性回归(CMLLR)相结合的方法来更新说话人模型、投影转换
    发表于 12-05 15:21 0次下载
    基于<b class='flag-5'>MAP</b>+CMLLR的说话人识别中发声力度问题

    mapreduce 中MAP进程的数量怎么控制?

    1.如果想增加map个数,则设置mapred.map.tasks 为一个较大的值2.如果想减小map个数,则设置mapred.min.split.size 为一个较大的值3.如果输入中有很多小文件,依然想减少
    发表于 01-02 14:04 1863次阅读
    mapreduce 中<b class='flag-5'>MAP</b>进程的数量怎么控制?

    mapreduce设置map个数_mapreduce设置map内存

    map阶段读取数据前,FileInputFormat会将输入文件分割成split,split的个数决定了map的个数。
    发表于 01-02 14:26 1.1w次阅读
    mapreduce设置<b class='flag-5'>map</b>个数_mapreduce设置<b class='flag-5'>map</b>内存

    Python基础变量类型—List分析

    本文基于Python基础,主要介绍了Python基础中list列表,通过list列表的两个函数 ,对list的语法做了详细的讲解,用丰富的案例 ,代码效果图的展示帮助大家更好理解 。
    的头像 发表于 12-24 17:37 1049次阅读

    Automotive Recommended Products List

    Automotive Recommended Products List
    发表于 02-03 15:27 0次下载
    Automotive Recommended Products <b class='flag-5'>List</b>

    什么是 map

    map 容器,又称键值对容器,即该容器的底层是以红黑树变体实现的,是典型的关联式容器。这意味着,map 容器中的元素可以分散存储在内存空间里,而不是必须存储在一整块连续的内存空间中。跟任意其它类型容器一样,它能够存放各种类型的对象。
    的头像 发表于 02-27 15:41 2781次阅读

    什么是list

    list 容器,又称双向链表容器,即该容器的底层是以双向链表的形式实现的。这意味着,list 容器中的元素可以分散存储在内存空间里,而不是必须存储在一整块连续的内存空间中。
    的头像 发表于 02-27 15:52 2243次阅读

    Java8的Stream流 map() 方法

    之后,对集合可以进行 Stream 操作,使上面的处理更简洁。 概述 Stream 流式处理中有 map() 方法,先看下其定义,该方法在java.util.stream.Stream类中 可以看到
    的头像 发表于 09-25 11:06 1718次阅读
    Java8的Stream流 <b class='flag-5'>map</b>() <b class='flag-5'>方法</b>