[英]Java 8 lambda expression changes Collection multiple times
我有以下课程:
Doer,它仅执行Runnable的运行方法(将是lambda):
public class Doer {
final Runnable runnable;
public Doer(final Runnable runnable) {
this.runnable = runnable;
}
public void doSomething() {
runnable.run();
}
}
存储,这是一个可观察的数字存储:
import java.util.ArrayList;
import java.util.List;
import java.util.Observable;
public class Storage extends Observable {
final List<Integer> storage;
public Storage() {
this.storage = new ArrayList<>();
}
void add(int number) {
storage.add(number);
setChanged();
notifyObservers(number);
}
public List<Integer> getStorage() {
return storage;
}
}
过滤,防止Doer做太多事情;)
import java.util.Observable;
import java.util.Observer;
public class Filter implements Observer {
final Doer doer;
int counter;
final int nth;
public Filter(int nth, Storage store, Doer doer) {
this.doer = doer;
this.nth = nth;
store.addObserver(this);
}
@Override
public void update(Observable o, Object arg) {
counter++;
if (counter == nth)
doer.doSomething();
}
}
现在考虑以下单元测试:
import org.junit.Test;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
public class FilterTest {
@Test
public void testStore() throws Exception {
List<Collection<Integer>> numbers = new ArrayList<>();
Storage store = new Storage();
Filter filter = new Filter(2, store, new Doer(() -> {
numbers.add(store.getStorage());
System.out.println(numbers);
}));
System.out.println(numbers);
store.add(1);
System.out.println(numbers);
store.add(2);
System.out.println(numbers);
store.add(3);
System.out.println(numbers);
}
}
它产生结果:
[]
[]
[[1, 2]]
[[1, 2]]
[[1, 2, 3]]
我真的没有得到最后一行,为什么现在的数字是3,因为在lambda中没有执行numbers.add(3)?
该lambda仅被调用一次。 它将store
内部的List<Integer>
添加到numbers
。
请注意,lambda不会在store
复制List<Integer>
。 因此, numbers
包含与store
相同的List<Integer>
的引用。
如果添加了更多数量的List<Integer>
在store
,你会看到这些变化也在numbers
,因为内容numbers
是相同的参考List<Integer>
。
因此,当您执行store.add(3);
然后打印numbers
内容,您还将在其中看到3
。
将集合添加到lambda中的numbers
时,请尝试制作该集合的副本,并观察其中的区别:
Filter filter = new Filter(2, store, new Doer(() -> {
numbers.add(new ArrayList<>(store.getStorage()));
System.out.println(numbers);
}));
输出:
[]
[]
[[1, 2]]
[[1, 2]]
[[1, 2]]
不知道您的代码真正应该做什么,我假设您的numbers
集合未正确声明:
List<Collection<Integer>> numbers = new ArrayList<>();
这是一个整数集合的列表,因此,列表中的每个元素本身都应该是一个集合。 相反,它可能应该只是数字列表:
List<Integer> numbers = new ArrayList<>();
因此,您也必须更改Runnable
,因为您不想将整个存储添加到列表中,而只是将存储的内容添加到列表中:
() -> {
numbers.addAll(store.getStorage());
System.out.println(numbers);
};
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.