FilteredList/SortedList

Jonathan Giles jonathan.giles at oracle.com
Thu Jan 3 20:08:39 PST 2013


On 3/01/2013 10:10 p.m., Martin Sladecek wrote:
>> 1) always in a sorted state
> OK, this one should be simple.
>
> tableView.setItems(myList.transform().sorted( (o1,o2) -> 
> doSomeComparison(o1, o2) );
Seems reasonable.
>
> Now this is sorting set explicitly by the developer, I understand you 
> might want to do some sorting based on columns. Then you can store 
> "items" internally (for the original order, they won't change) and use 
> some different field for the actual work, doing something like
>
> setCurrentItems(items.transform().sorted(currentColumnComparator));
 From a TableView perspective, I'm dealing in ObservableLists (not 
TransformationLists). I'm just wanting to clarify how you foresee things 
changing when this API is available.

Presently when a sort occurs, I essentially create a Comparator (based 
on the Comparators of the sort columns), and then run 
FXCollections.sort(list, comparator) (or whatever the API is). This 
sorts the list in place.

When we have transform() on all ObservableLists, is the recommended 
approach to always run a new list.transform().sorted(comparator) call 
every time the sort order changes, and then set the new result in the 
tableview items property?

Also, I guess I can internally know that I can return to the original 
sort order when the tableview items list is an instance of a 
TransformationList, as then I can do something along the lines of 
tableView.setItems(tableView.getItems().getOriginalSource()). If the 
list is not a TransformationList, I will have to not support returning 
to the original sort order (as is the case now).
>
> To return back to the original order, this should be enough:
>
> setCurrentItems(items);
>
> To modify the table (like adding a new item), you would use items 
> directly. The actual position where to put the new item in "items" can 
> be determined by calling getOriginalSourceIndex(int index) on the 
> previous table item from "currentItems".
>
>> 2) able to filtered based on a user typing
> Now this is something that was also problematic in the original API. 
> When the user types, the Predicate/Matcher changes, so originally we 
> had to keep the filteredlist reference and call 
> filteredList.setMatcher(matcher). As filtered list cannot rely on the 
> fact that the set matched by the new matcher is a subset of the 
> previous one, everything is processed again. Trying to create a 
> meaningful ListChangeListener.Change might result is a huge number of 
> sub-changes, so originally, I just fired a "everything was removed & 
> new items were added" change, which means whole table was rebuilt.
If your concern is simply around the cost of rebuilding the table 
(rather than running the filter over all items), then I wouldn't worry 
about that. The TableView frequently rebuilds everything, and so that is 
a relatively cheap operation to perform.
>
> The same problems are in the new API -
> *  need to keep a reference to change the filter (in this case it's 
> the reference of the underlying list and a filtered() call on it when 
> the predicate changes)
> *  optimize cases where new predicate matches a superset/subset of the 
> previous predicate's set.
>
> What about having another method for "mutable" predicates, like this?
>
> filtered(ObservableValue<? extends Predicate<? super E>> predicate);
>
> The filtered list would bind to the ObservableValue (which could be a 
> property, expression, etc...) and refilter on change. As the user 
> types, you just need to update the property with the new Predicate.
Sounds reasonable, but I'm really keen to test out these ideas in a 
simple UI app.

-- Jonathan



More information about the openjfx-dev mailing list