-
Bug
-
Resolution: Fixed
-
P4
-
fx2.0
when removing a bunch of items from a list, the sourceIndex returned by a wrapping sortedList can be invalid in a listener registered on the sortedList. In that case access of the underlying list with the given index throws an AIOOB
Reason is that the items in the underlying list are already removed at the time of sorted's listener notification. While Client code could guard against (by range checking always), that should be done in the sortedList itself: f.i. let it return -1 if no longer valid. TestCase to reproduce (run against b32):
public class SourceIndexBug extends TestCase {
/**
* Sorted list: sourceIndex returns a value that's invalid in the
* source list during batch removal of items
*/
@Test
public void testSourceIndex() {
final ObservableList<Double> sourceList = FXCollections.observableArrayList(
1300., 400., 600.
);
// the list to be removed again, note that its highest value is greater
// then the highest in the base list before adding
List<Double> other = Arrays.asList(
50., -300., 4000.
);
sourceList.addAll(other);
// wrap into a sorted list and add a listener to the sorted
final SortedList<Double> sorted = new SortedList<Double>(sourceList);
ListChangeListener<Double> listener = new ListChangeListener<Double>() {
@Override
public void onChanged(Change<? extends Double> c) {
// grab sourceIndex of last (aka: highest) value in sorted list
int sourceIndex = sorted.getSourceIndex(sorted.size() - 1);
// if valid access the value in source
if (sourceIndex >= 0)
sourceList.get(sourceIndex);
}
};
sorted.addListener(listener);
sourceList.removeAll(other);
}
}
Reason is that the items in the underlying list are already removed at the time of sorted's listener notification. While Client code could guard against (by range checking always), that should be done in the sortedList itself: f.i. let it return -1 if no longer valid. TestCase to reproduce (run against b32):
public class SourceIndexBug extends TestCase {
/**
* Sorted list: sourceIndex returns a value that's invalid in the
* source list during batch removal of items
*/
@Test
public void testSourceIndex() {
final ObservableList<Double> sourceList = FXCollections.observableArrayList(
1300., 400., 600.
);
// the list to be removed again, note that its highest value is greater
// then the highest in the base list before adding
List<Double> other = Arrays.asList(
50., -300., 4000.
);
sourceList.addAll(other);
// wrap into a sorted list and add a listener to the sorted
final SortedList<Double> sorted = new SortedList<Double>(sourceList);
ListChangeListener<Double> listener = new ListChangeListener<Double>() {
@Override
public void onChanged(Change<? extends Double> c) {
// grab sourceIndex of last (aka: highest) value in sorted list
int sourceIndex = sorted.getSourceIndex(sorted.size() - 1);
// if valid access the value in source
if (sourceIndex >= 0)
sourceList.get(sourceIndex);
}
};
sorted.addListener(listener);
sourceList.removeAll(other);
}
}
- relates to
-
JDK-8114666 SortedList AIOOB replacing last element in wrapped list
- Resolved