首页 > 编程语言 >Java8使用Stream API转换Map遇到的2种异常报错和解决思路

Java8使用Stream API转换Map遇到的2种异常报错和解决思路

时间:2023-04-26 23:44:29浏览次数:88  
标签:AbstractPipeline Map toMap java Stream stream Collectors util 报错

问题

java8提供了Stream API,配合Lambda表达式,让开发者能对集合对象进行便利、高效的操作。
在日常业务开发中,有个经常用到的场景是将List类型对象转换为Map类型对象,方便后续操作。
在java8之前,这种转换需要先new一个Map对象,遍历list然后通过Map#put来初始化。
使用java8后,可方便的使用list.stream().collect(Collectors.toMap(...))进行转换。
然而这种转换可能会遇到转换失败程序报错的情况,这里总结了常见的2种报错的例子和解决思路。

示例和分析

1.java.lang.IllegalStateException

场景:有重复的key

例:

public static void main(String[] args) {
    Person p1 = new Person("aa", 18);
    Person p2 = new Person("bb", 20);
    Person p3 = new Person("cc", 18);
    List<Product> list = Stream.of(p1, p2, p3).collect(Collectors.toList());

    Map<Integer, Person> map = list.stream().collect(Collectors.toMap(p -> p.getAge(), p -> p);
    System.out.println(map);
}

@NoArgsConstructor
@AllArgsConstructor
@Data
static class Person {

    private String name;

    private Integer age;
}

Collectors.toMap里使用里使用Person类的age字段为key,由于p1p3age值都为18,上面程序运行错误信息如下:

Exception in thread "main" java.lang.IllegalStateException: Duplicate key StreamToMapTest1.Person(name=aa, age=18)
	at java.util.stream.Collectors.lambda$throwingMerger$0(Collectors.java:133)
	at java.util.HashMap.merge(HashMap.java:1254)
	at java.util.stream.Collectors.lambda$toMap$58(Collectors.java:1320)
	at java.util.stream.ReduceOps$3ReducingSink.accept(ReduceOps.java:169)
	at java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1382)
	at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:482)
	at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:472)
	at java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:708)
	at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
	at java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:499)

解决思路:使用Collectors.toMap的3个参数的重载方法,第3个参数指定mergeFunction

Map<Integer, Person> map = list.stream().collect(Collectors.toMap(p -> p.getAge(), p -> p, (o, n) -> n));

(o, n) -> n)表示遇到重复需要合并时使用新值;
如果写(o, n) -> o)则是使用旧值;
o和n是old和new的缩写,便于理解,也可以用其它变量名。

2.java.lang.NullPointerException

场景:value里有null值

例:

public static void main(String[] args) {
    Product p1 = new Product("1001", "aaa");
    Product p2 = new Product("1002", null);
    Product p3 = new Product("1003", "bbb");
    List<Product> list = Stream.of(p1, p2, p3).collect(Collectors.toList());

    Map<String, String> map = list.stream().collect(Collectors.toMap(p -> p.getProductCode(), p -> p.getBarCode(), (o, n) -> n));
    System.out.println(map);
}

@NoArgsConstructor
@AllArgsConstructor
@Data
private static class Product {

    private String productCode;

    private String barCode;
}

Collectors.toMap里使用里使用Product类的barCode字段为value,由于p2barCode值是null,上面程序运行错误信息如下:

Exception in thread "main" java.lang.NullPointerException
	at java.util.HashMap.merge(HashMap.java:1225)
	at java.util.stream.Collectors.lambda$toMap$58(Collectors.java:1320)
	at java.util.stream.ReduceOps$3ReducingSink.accept(ReduceOps.java:169)
	at java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1382)
	at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:482)
	at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:472)
	at java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:708)
	at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
	at java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:499)

解决思路:
1.考虑把value为null的通过filter过滤掉再转换map
注:这是思路适用于不需要null的场景,可能有的场景map里需要保留null值,然后对map做进一步处理,可考虑思路2。

2.使用stream().collect的重载方法来创建Map

HashMap<Object, Object> map = list.stream().collect(HashMap::new, (m, p) -> m.put(p.getProductCode(), p.getBarCode()), HashMap::putAll);

参考

标签:AbstractPipeline,Map,toMap,java,Stream,stream,Collectors,util,报错
From: https://www.cnblogs.com/cdfive2018/p/17349402.html

相关文章

  • Java Lambda Stream
    ::方法使用条件:lambada表达式的主体仅包含一个表达式,且lambada表达式只调用一个已经存在的方法;被引用的方法的参数列表与lambada表达式的输入输出一致以下是Java8中方法引用的一些语法:静态方法引用(staticmethod)语法:classname::methodname例如:Person::getAge对象的实例方......
  • java线程之Semaphore
    Semaphore是信号量,用于线程间同步。例子,公交车上大概有24个座位,但是车上总共有40个人,那么,只要有一个人下车,另一个人就能得到一个座位,假设到终点站之前,每个人都能坐下。代码如下:packagecom.concurrent;importjava.util.Random;importjava.util.concurrent.CountDownLatch;imp......
  • yum 安装的nginx 添加其他模块 stream
    需求:生产有个接口是通过socket通信。nginx1.9开始支持tcp层的转发,通过stream实现的,而socket也是基于tcp通信。实现方法:Centos7.2下yum直接安装的nginx,添加新模块支持tcp转发;重新编译Nginx并添加--with-stream参数。实现过程:1. 查看nginx版本模块[root@pre~]#nginx-V......
  • macOS下生成pdf报错:No wkhtmltopdf executable found
    重点:不要在PyCharm里直接安装 wkhtmltopdf!!!从wkhtmltopdf官网下载macOS下的pdg安装包,下载页面:wkhtmltopdf下载完后安装,通过which找到安装路径importpdfkitconfig=pdfkit.configuration(wkhtmltopdf='/usr/local/bin/wkhtmltopdf')pdfkit.from_string("abc","0.pdf&quo......
  • 服务器断电后启动失败报错:Generating /run/initramfs/rdsosreport.txt
    一、现象服务器断电,然后启动时发现起不来,连接显示器发现报错,如下所示: 原因:一般是服务器突然断电导致文件损坏所致,只要修复回去就好二、解决过程2.1寻找/dev/*-root文件说明: /dev/mapper目录下一般有三个文件,其中 centos-root是我们需要修复的。有些服务器的文件名称......
  • 解决 c3p0报错 Establishing SSL connection without server's identity verification
    解决c3p0报错EstablishingSSLconnectionwithoutserver'sidentityverificationisnotrecommended  ?useSSL=false<c3p0-config><default-config><propertyname="driverClass">com.mysql.jdbc.Driver</property>......
  • 如何实现vue项目中使用Baidu Map,有多个点,鼠标移入出现文字标注,移除消失文字标注,并且点
    直接来案例,再分析;<template> <divref="map"style="height:100vh;"></div></template><script>exportdefault{ data(){  return{   points:[    {lng:116.404,lat:39.915,name:'北京天安门......
  • Correct the classpath of your application so that it contains a single, compatib
    1.背景有时候引入包有冲突,比如在Maven项目中的不同模块多次重复引入等这里遇到的问题是重复映入了如下包:<dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.0-RELEASE</vers......
  • 解决Python中报错RequestsDependencyWarning: urllib3 (1.26.9) or chardet (5.1.0)/c
      在运行requests包时,出现了以下报错信息:RequestsDependencyWarning:urllib3(1.26.9)orchardet(5.1.0)/charset_normalizer(2.0.12)doesn'tmatchasupportedversion!warnings.warn("urllib3({})orchardet({})/charset_normalizer({})doesn'tmatchasu......
  • 【FAQ】关于JavaScript版本的华为地图服务Map的点击事件与Marker的点击事件存在冲突的
    一. 问题描述创建地图对象,并添加marker标记,对map和marker均添加了点击事件;<body><script>functioninitMap(){//创建地图对象constmap=newHWMapJsSDK.HWMap(document.getElementById('map'),{center:{lat:39.36322,lng:......