Java资深小白,不足之处,或者有任何错误欢迎指出。 --蓝紫

在下面的代码中,List集合使用stream流及中间操作Lambda表达式访问外部变量count 进行累加操作,第20行编译报错:Local variable count defined in an enclosing scope must be final or effectively final。原因是Lambda访问外部变量有一个非常重要的限制,即变量不可变。

 @GetMapping("/count")@ApiOperation(value = "数量")public Long count() {// 用户能够访问的系统,通过授权菜单获得List<PortalSystem> systemList = portalSystemService.userSystem();AtomicLong atoTotalCount = new AtomicLong();Long count = 0L;// 循环系统,得到每个系统的类型LocalThreadData localData = LocalThreadMap.get();systemList.parallelStream().forEach(e -> {LocalThreadMap.put(localData);try {String frameType = e.getFramework();TodoBase todoInstance = getTodo(frameType);Long totalCount = todoInstance.totalCount(e.getOrgId());if (totalCount == null) {totalCount = 0L;}//此处报错count = count + totalCount;} catch (Exception ex) {log.error("获取在办数量异常", ex);} finally {LocalThreadMap.clear();}});return count;}

根据提示我们必须使用final修饰count,但此处业务是需要做累加需要修改变量,这里也是不可避免需要使用for增强循环,而for循环中不存在该问题。

解决在foreach做累加的报错

因为是获取多系统的数据,所以使用并行执行的流来提高多线程的任务速度,即:parallelStream,这里就涉及到线程安全问题了。比较两全其美的解决方案是采用AtomicLong(Long的原子类)来替换Long,AtomicLong可以进行原子操作的变量,并且能使得线程安全,修改后的代码如下。

 @GetMapping("/count")@ApiOperation(value = "数量")public Long count() {// 用户能够访问的系统,通过授权菜单获得List<PortalSystem> systemList = portalSystemService.userSystem();//使用原子类LongAtomicLong atoTotalCount = new AtomicLong();// 循环系统,得到每个系统的类型LocalThreadData localData = LocalThreadMap.get();systemList.parallelStream().forEach(e -> {LocalThreadMap.put(localData);try {String frameType = e.getFramework();TodoBase todoInstance = getTodo(frameType);Long totalCount = todoInstance.totalCount(e.getOrgId());if (totalCount == null) {totalCount = 0L;}//累加操作atoTotalCount.addAndGet(totalCount);} catch (Exception ex) {log.error("获取在办数量异常", ex);} finally {LocalThreadMap.clear();}});//返回值return atoTotalCount.longValue();}

第20行中的addAndGet()方法,是AtomicLong的常见方法之一,该方法是先将totalCount的值加上atoTotalCount的值,再获取其总和的值。

特别地,如果使用对象进行foreach循环修改,对其属性进行操作,也不存为这个问题,因为声明一个对象的初始值是内存地址,修改内容不会修改内存地址值,实例如下。

拓展点:
1.AtomicLong的几个常用方法?---------->高并发编程之AtomicLong讲解
2.Long类型对应的concurrent包的类是AtomicLong,想了解concurrent包?---------->Java 并发工具箱之concurrent包
3.什么是parallelStream?---------->深入浅出parallelStream

解决ERROR:Local variable count defined in an enclosing scope must be final or effectively final相关推荐

  1. foreach无法给外部变量赋值(Local variable decimal defined in an enclosing scope must be final or effectively )

    报错信息如下: Local variable decimal defined in an enclosing scope must be final or effectively final 原因:在 ...

  2. Java报错---Cannot refer to the non-final local variable user defined in an enclosing scope

    昨晚在另一台机电脑上正常运行,今天办公室内的电脑运行出现以下报错 Cannot refer to the non-final local variable user defined in an enc ...

  3. 出现Cannot refer to the non-final local variable guoDeGang defined in an enclosing scope

    代码: public interface Star {public void crossTalk(int money);public void sing(int money);public void ...

  4. 关于Julia1.0及以后版本的for循环产生错误ERROR: UndefVarError: variable not defined的解决方法

    目录 一.错误 二.目前的解决方法 三.结语 一.错误 1.在Julia1.0版本中,定义在for循环之外的变量不能出现在for循环里,否则会如下错误: ERROR: UndefVarError: v ...

  5. 解决error mounted is not defined no-undef

    "App.vue4:3error'mounted' is not defined no-undef" 这个 其实是个语法问题 因为第一次接触VUE 对其语法完全不懂鸭 我的天 搞死 ...

  6. 解决error ‘XXX‘ is not defined no-undef且项目没有eslintrc.js文件问题

    问题描述 这是因为eslint的语法校验导致的问题,文件是通过public的index.html中<script src="xxxxxx.js"></script ...

  7. NameError: free variable ‘***‘ referenced before assignment in enclosing scope

    错误原因:可能在你定义的类里面没有对***事先定义而直接就用了.(当然网上还有那种'***'这个是不是全局变量的问题).我指的这个也是可以造成报这个错误的一种情况. 举例如下: 注意上图画线部分,在定 ...

  8. 深入浅出理解 Variable used in lambda expression should be final or effectively final

    翻译:lambda 表达式中使用的变量应该是 final 或者有效的 final 原因解析:lambda表达式(多用在线程领域),是由匿名内部类演变来的. 匿名内部类产生的对象一般存放在JVM的堆区域 ...

  9. Error0---local variable S is accessed from within inner class; needs to be declared final

    local variable S is accessed from within inner class; needs to be declared final在内部类当中不能引用本地变量s,需要被声 ...

  10. Neither the JAVA_HOME nor the JRE_HOME environment variable is defined 完美解决(tomcat error)

    error: Linux下启动和关闭tomcat报错,如下图所示: Neither the JAVA_HOME nor the JRE_HOME environment variable is def ...

最新文章

  1. Java学习之if语句
  2. Tomcat中配置MySQL数据库连接池
  3. linux内核全局变量重定位,关于可重定位文件中全局变量的一个重定位疑惑,借各位牛刀一用^...
  4. Leetcode--442. 数组中重复的数据
  5. 未来无限可能 戴尔易安信开启中国新征程
  6. Python基础-pyqt5
  7. POJ--3278 Catch That Cow
  8. 大数据Hadoop最新版实战Linux Ubuntu 16.04安装与运行测试例子...
  9. 【速看】拼多多云服务平台流程信息流出
  10. win10 svn无法成功完成操作,因为文件包含病毒或潜在的垃圾软件
  11. 3.26 文字工具的使用 [原创Ps教程]
  12. 记录一次使用ParallelGC导致线上FGC频繁、耗时长的原因
  13. 用python处理excel数据、求线性回归方程的r值_Python 线性回归计算r-squared方法
  14. 从《生活计划》实践,剖析自我执行力
  15. MAC 活动监视器部分状态缺失
  16. Spring和SpringBoot简介
  17. Java查找一个字符串中某字符出现的次数
  18. unity3d websocket
  19. iOS5打开系统setting页面
  20. 2012龙年北京庙会全攻略

热门文章

  1. FFmpeg —— 14.示例程序(八):音频编码器(PCM编码为AAC)
  2. Redis集群cluster:增加删除(伸缩)节点操作步骤
  3. 计算机科学是ei期刊吗,EI计算机期刊有哪些
  4. brew upgrade出现It seems there is already an App at的解决方法
  5. day04 1113 红与黑(flood fill算法,即DFS,BFS)
  6. 如何学习单片机?学习单片机的四个步骤
  7. ARCore从零到一 (1) 搭建开发环境
  8. 交易开拓者-附录一:计算公式
  9. 大学英语计算机统考怎么过,2011年9月大学英语B 统考 计算机网考样题
  10. 电影评论画像制作(豆瓣肖申克的救赎为例)