Java forEach lambda抛出concurrentModificationException
下面的方法抛出Java forEach lambda抛出concurrentModificationException,java,foreach,java-8,Java,Foreach,Java 8,下面的方法抛出ConcurrentModificationException的原因可能是什么 static Set<String> setOfAllocAccountsIn(final @NotNull Execution execution) { final Set<String> allocAccounts = new HashSet<>(); execution.legs().forEach(leg -> leg.a
ConcurrentModificationException
的原因可能是什么
static Set<String> setOfAllocAccountsIn(final @NotNull Execution execution) {
final Set<String> allocAccounts = new HashSet<>();
execution.legs().forEach(leg -> leg.allocs().forEach(alloc -> {
if (alloc.account() != null) {
allocAccounts.add(alloc.account());
}
}));
return allocAccounts;
}
使用simplefor循环
可以很好地工作。该方法由多个线程使用其自己的执行对象副本调用
使用简单for循环的解决方案:
static Set<String> setOfAllocAccountsIn(final @NotNull Execution execution) {
final Set<String> allocAccounts = new HashSet<>();
for (final ExecutionLeg executionLeg : execution.legs()) {
for (final ExecutionAlloc executionAlloc : executionLeg.allocs()) {
if (executionAlloc.account() != null) {
allocAccounts.add(executionAlloc.account());
}
}
}
return allocAccounts;
}
静态集合集合allocaccountsin(最终@NotNull执行){
最终集合allocAccounts=新HashSet();
for(final ExecutionLeg ExecutionLeg:execution.legs()){
对于(final ExecutionAlloc ExecutionAlloc:executionLeg.allocs()){
if(executionAlloc.account()!=null){
allocAccounts.add(executionAlloc.account());
}
}
}
返回allocAccounts;
}
我觉得它与静态方法有关,它的局部变量由多个线程访问,但根据理论,它将是线程局部变量,不会被共享。给我一些时间写一些简单的例子 您的逻辑可以是这样的:
return execution.legs().stream()
.flatMap(leg -> leg.allocs().stream())
.map(executionAlloc -> executionAlloc.account())
.filter(Objects::nonNull)
.collect(Collectors.toSet());
- 您正在
内部使用forEach
(这里我将其替换为forEach
)flatMap
- 然后检查每个元素的
是否为null(我将其替换为alloc.account()
)filter
- 然后,如果条件正确,则将其添加到集合中(我将其替换为
)收集
- 您的逻辑可以是这样的:
return execution.legs().stream()
.flatMap(leg -> leg.allocs().stream())
.map(executionAlloc -> executionAlloc.account())
.filter(Objects::nonNull)
.collect(Collectors.toSet());
- 您正在
内部使用forEach
(这里我将其替换为forEach
)flatMap
- 然后检查每个元素的
是否为null(我将其替换为alloc.account()
)filter
- 然后,如果条件正确,则将其添加到集合中(我将其替换为
)收集
legs
,allocs
等等?@Ben…让我用一个简单的例子来更新它。如何创建Execution
对象的副本?请发布一个。是否有可能其中一个方法修改了其中一个涉及的集合(例如可能executionAlloc.account()
modifies on of the collection?)stacktrace说了什么。什么是legs
,allocs
等等?@Ben…让我用一个简单的例子来更新它。如何创建Execution
对象的副本?请发布一个。是否有可能其中一个方法修改了其中一个涉及的集合(例如可能executionAlloc.account()
modifies on of the collection?)是的,此代码比OP的代码更干净,但是,进行此更改将如何解决ConcurrentModificationException
?@Eran老实说,我不知道OP可以从哪里获得ConcurrentModificationException
,因为leg.allocs()
的结果有一个forEach
方法,它不是数组,而是一个集合,所以它应该是leg.allocs().stream()
而不是Stream.of(leg.allocs())
。此外,如果您在过滤器
之前执行.map(executionAlloc->executionAlloc.account())
,那么您会获得很多好处,因为这样,谓词就变成了一个简单的null
-检查(过滤器(对象::非null)
),而不需要重复帐户()
调用。这是正确的@Holger感谢您提供的详细信息,我编辑了我的回答是的,这个代码比OP的代码更干净,但是做这个更改如何解决ConcurrentModificationException
?@Eran老实说,我不知道OP可以从哪里得到ConcurrentModificationException
,因为leg.allocs()
的结果有一个forEach
方法,它不是数组,但可能是集合,因此它应该是leg.allocs().stream()
,而不是stream.of(leg.allocs())
。此外,如果您在过滤器
之前执行.map(executionAlloc->executionAlloc.account())
,那么您会获得很多好处,因为这样,谓词就变成了一个简单的null
-检查(过滤器(对象::非null)
),而不需要重复帐户()
调用。这是正确的@Holger感谢您提供的详细信息,我编辑我的答案