我可以在使用Iterable.forEach(消费者)迭代元素时更改元素吗?

问题描述 投票:0回答:4

我可以在使用Iterable.forEach(消费者)迭代元素时更改元素吗?或者在Consumer.accept(E)中,我只能读取底层Iterable的元素,但不能更改它们?

如果我可以改变它们,那么正确的语法是什么?

ArrayDeque d = new ArrayDeque<Integer>();
d.add(1);
d.add(2);
d.add(3);
d.add(4);

Consumer<Integer> cons = (e)->{e = e*10;}; // compiles!

d.forEach(cons);

System.out.println(d); // 1 2 3 4 not 10 20 30 40
java foreach iterable
4个回答
2
投票

你要做的是和以下一样:

for (Integer e : d) {
   e = e * 10;
}

但是,分配给e并不会改变其在双端队列中的价值。

要做你想做的,做到这一点。

 d = d.stream().map(a -> a * 10).collect(
            Collectors.toCollection(ArrayDeque::new));
 System.out.println(d);

1
投票

不,你在使用forEach时不能修改元素,因为它的actionConsumer,只有accepts的值。 forEach方法的示例代码段

default void forEach(Consumer<? super T> action)
 for (T t : this)
     action.accept(t);

要关注的主要是它不会产生任何价值。


1
投票

不,你不能。根据documentation for ArrayDeque

这个类的迭代器方法返回的迭代器是快速失败的:如果在创建迭代器之后的任何时候修改了deque,除了通过迭代器自己的remove方法之外,迭代器通常会抛出一个ConcurrentModificationException


1
投票

forEach采用一个不返回任何内容的Consumer参数,根据您的示例,每个e都是ArrayDeque中元素的副本,因此您无法使用forEach替换元素。

如果你想在一个任务的每个元素上做e*10(比如打印它们),你可以将ArrayDeque转换为Stream,并使用map():

d.stream().map(e -> e*10).forEach(e -> System.out.println(e));

这样做会表明Deque中的每个元素都乘以10。

如果你想真正替换ArrayDeque中的元素,

d = d.stream().map(e -> e*10).collect(Collectors.toCollection(ArrayDeque::new));
© www.soinside.com 2019 - 2024. All rights reserved.