i have to arrays: arrA
and arrB
. arrA
and arrB
are Lists of objectss of diffrent types and add
function converts objects A
to objects B
. I want to add each object from arrA to arrB and remove that object from arrA. Im trying to do this by stream:
arrA.stream().foreach(c -> {arrB.add(c); arrA.remove(c);});
when i execute this, two things are happening:
i gues it's because length of array is decreased after each remove()
call and the counter of iterations is increased (only objects under odd indexes are passed to arrB
)
Now i could solve this by copying array in one stream call and then remove objects in second stream call but this doesnt seem correct for me.
What would be proper solution to this problem?
EDIT. Additional information: in real implementation this list if previously filtered
arrA.stream().filter(some condition).foreach(c -> {arrB.add(c); arrA.remove(c);});
and its called few times to add elements meeting diffrent conditions to diffrent lists (arrC, arrD
etc.) but each object can be only on one list
As the others have mentioned, this is not possible with foreach
- as it is impossible with the for (A a: arrA)
loop to remove elements.
In my opinion, the cleanest solution is to use a plain for while
with iterators - iterators allow you to remove elements while iterating (as long as the collection supports that).
Iterator<A> it = arrA.iterator()
while (it.hasNext()) {
A a = it.next();
if (!check(a))
continue;
arrB.add(a);
it.remove();
}
This also saves you from copying/cloning arrA
.
Streams are designed to be used in a more functional way, preferably treating your collections as immutable.
The non-streams way would be:
arrB.addAll(arrA);
arrA.clear();
However you might be using Streams so you can filter the input so it's more like:
arrB.addAll(arrA.stream().filter(x -> whatever).toList())
then remove from arrA (thanks to @Holgar for the comment).
arrA.removeIf(x -> whatever)
If your predicate is expensive, then you could partition:
Map<Boolean, XXX> lists = arrA.stream()
.collect(Collectors.partitioningBy(x -> whatever));
arrA = lists.get(false);
arrB = lists.get(true);
or make a list of the changes:
List<XXX> toMove = arrA.stream().filter(x->whatever).toList();
arrA.removeAll(toMove);
arrB.addAll(toMove);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With