On Wed, 4 Jan 2023 05:28:10 GMT, Nir Lisker <nlis...@openjdk.org> wrote:

>> John Hendrikx has updated the pull request incrementally with two additional 
>> commits since the last revision:
>> 
>>  - Clean up expression classes repeated null checks
>>  - Use instanceof with pattern matching in a few spots
>
> I took a closer look at the sorting-related classes. I think that the design 
> there is not ideal. Fixing it might be out of scope for this PR. I wouldn't 
> mind fixing it myself, by the way.
> 
> The way the JDK treats soring on lists is with a single `sort(Comparable c)` 
> method that, when receiving `null`, assumes that the elements are 
> `Comparable` and throws if not. `Collections` has 2 static sorting methods 
> that help enforce this condition, where the one that doesn't take a 
> `Comparator` passes `null` to the one that does.
> 
> JavaFX tries to emulate this. `FXCollections` has the same 2 methods for 
> `ObservableList`, but one doesn't call the other. The asymmetry comes from 
> `SortableList` (which doesn't live up to its name - non-sortable lists can 
> also implement it). It defines a 0-argument method and a 
> `Comparator`-argument method as different behaviors, instead of one calling 
> the other. This is deferred to its implementations, `ObservableListWrapper` 
> and `ObservableSequentialListWrapper`, which make the differentiation by, 
> again, calling 2 different methods on `SortHelper`.
> 
> I suggest that the argument check be made at the lowest level, like in the 
> JDK (inside `Arrays` sort method). First, `FXCollections` can change to:
> 
> 
>     public static <T extends Comparable<? super T>> void 
> sort(ObservableList<T> list) {
>         sort(list, null); // or Comparator.naturalOrder() instead of null
>     }
> 
>     public static <T> void sort(ObservableList<T> list, Comparator<? super T> 
> c) {
>         if (list instanceof SortableList) {
>             list.sort(c);
>         } else {
>             List<T> newContent = new ArrayList<>(list);
>             newContent.sort(c);
>             list.setAll(newContent);
>         }
>     }
> 
> 
> `SortableList` then removes its `sort()` method, and now it's just overriding 
> `List::sort(Comparator)` without doing anything with it, so it can be removed 
> too, and it's left as a marker interface for the special sorting in 
> `SortHelper` (I haven't understood yet why it's better , I need to dig there 
> more):
> 
> 
> public interface SortableList {}
> 
> 
> Now `ObservableListWrapper` and `ObservableSequentialListWrapper` also remove 
> `sort()`, and override `List::sort(Comparator)` directly and in accordance 
> with its contract, passing the (possibly `null`) comparator to `SortHelper`, 
> which is akin to the JDK's `Arrays::sort` method.
> 
> Now I need to look into `SortHelper` to see what it does exactly and how to 
> change it. I think it doesn't need the `sort(List<T> list)` method too now 
> because it doesn't really enforce that the elements are `Comparable`, it will 
> naturally throw if not.
> 
> ---
> 
> In my opinion, this is the design flaw: `ObservableList` should have 
> overridden `List`'s sort method to specify that its sorting is done as one 
> change:
> 
> 
> public interface ObservableList<E> extends List<E>, Observable {
> 
>     @Override
>     default void sort(Comparator<? super E> c) {
>         var newContent = new ArrayList<>(this);
>         newContent.sort(c);
>         setAll(newContent);
>     }
> 
> 
> Then we wouldn't need the `SortableList` marker because `FXCollections` could 
> just call this method directly (like `Collections` does, which means that 
> `FXCollections`'s methods are not needed anymore, though we can't remove 
> them), and whichever implementation wants to do a more efficient sorting, 
> like `ObservableListWrapper`, can override again.
> This will be a behavioral change, though, because the generated change events 
> differ.

@nlisker I think I made all modifications requested, is there anything else 
that should be done here? Do you want the sort changes to be made or an issue 
be filed for it?

-------------

PR: https://git.openjdk.org/jfx/pull/972

Reply via email to