I have the following classes:
Doer, which just executes the run-method of the Runnable (will be a lambda):
public class Doer {
final Runnable runnable;
public Doer(final Runnable runnable) {
this.runnable = runnable;
}
public void doSomething() {
runnable.run();
}
}
Storage, which is a Observable number store:
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;
}
}
Filter, preventing the Doer from doing so much ;)
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();
}
}
Now consider the following Unit Test:
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);
}
}
It produces the results:
[]
[]
[[1, 2]]
[[1, 2]]
[[1, 2, 3]]
I really do not get the last line, why is the 3 now in numbers, since numbers.add(3) has not been executed in the lambda?
The lambda is called only once. It's adding the List<Integer>
that's inside store
to numbers
.
Note that the lambda is not making a copy of the List<Integer>
in store
. So, numbers
contains a reference to the same List<Integer>
as what is in store
.
If you add more numbers to the List<Integer>
in store
, you see those changes also in numbers
, because the content of numbers
is a reference to the same List<Integer>
.
So when you do store.add(3);
and then print the content of numbers
, you'll also see the 3
in there.
Try making a copy of the collection when you add it to numbers
in the lambda, and see the difference:
Filter filter = new Filter(2, store, new Doer(() -> {
numbers.add(new ArrayList<>(store.getStorage()));
System.out.println(numbers);
}));
Output:
[]
[]
[[1, 2]]
[[1, 2]]
[[1, 2]]
Without knowing what your code is really supposed to do, I assume your numbers
collection is not declared correctly:
List<Collection<Integer>> numbers = new ArrayList<>();
This is a list of collections of integers, so every element of your list is supposed to be a collection by itself. Instead, it should probably be just a list of numbers:
List<Integer> numbers = new ArrayList<>();
So you will also have to change the Runnable
too, as you don't want to add the entire storage to your list but just the content of the storage:
() -> {
numbers.addAll(store.getStorage());
System.out.println(numbers);
};
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.