MultiReaderFastList returning incorrect types for select, selectWith, reject, rejectWith
donraab opened this issue · comments
A complicated but hopefully minor issue was discovered during a workshop for Grace Hopper Celebration. A new contributor upgraded the Eclipse Collections Kata to version 12.0.0.M3 and a test began failing in a class called MultiReaderCollectionsTest
. The methods select
, selectWith
, reject
, rejectWith
were were pulled up in the following PR.
These methods are now returning a MultiReaderFastList
instead of a FastList
. From an interface perspective, this is fine. Unfortunately, there is a behavior change because MultiReaderList implementations do not allow iterator to be used, so methods like equals will not work without taking an explicit lock.
The simplest solution would be to return the methods to their previous state. An alternative solution would be to make sure there are covariant overrides for select
, selectWith
, reject
, rejectWith
that return MultiReaderList
.
This is the failing test code in the Eclipse Collections Kata using 12.0.0.M3. The test was disabled as a short term resolution
This is the modified version of the code I had to write in order to get the test to pass. Note the explicit casts that were required due to the lack of covariant overrides.
@Test
@Tag("SOLUTION")
public void multiReaderListFiltering()
{
MultiReaderList<Integer> list =
Lists.multiReader.with(1, 2, 3, 4, 5);
// equals has a hidden iterator so use read lock
list.withReadLockAndDelegate(delegate ->
Assertions.assertEquals(Interval.oneTo(5), delegate));
Predicate<Integer> isEven = each -> each % 2 == 0;
// TODO: MultiReaderFastList is now returning a MultiReaderFastList for select and reject
// but is not providing a covariant override of the method so a cast is required
MultiReaderList<Integer> evens = (MultiReaderList<Integer>) list.select(isEven);
MultiReaderList<Integer> odds = (MultiReaderList<Integer>) list.reject(isEven);
PartitionList<Integer> partition = list.partition(isEven);
// equals has a hidden iterator so use read lock
evens.withReadLockAndDelegate(delegate -> Assertions.assertEquals(List.of(2, 4), delegate));
odds.withReadLockAndDelegate(delegate -> Assertions.assertEquals(List.of(1, 3, 5), delegate));
Assertions.assertEquals(evens, partition.getSelected());
Assertions.assertEquals(odds, partition.getRejected());
}
I think these four methods should be reverted back in the short-term, because they are now inconsistent with all of the collect
methods on MultiReaderFastList
which return the same type as a delegate, which would be FastList
.
Thoughts?
The select/reject methods usually return the same type, filtered down. The collect methods usually return a different type. I don't really see this as inconsistent.
I definitely think we should change equals and any other methods we find to stop using an iterator. I thought we had "no iterator" tests covering this case.
I guess we can revert the change too. These methods were returning the other types for a long time and nobody complained.