https://bugs.openjdk.java.net/browse/JDK-8197991
The performance of the selectAll and selectRange methods of the MultiSelectionModel class has been greatly improved. This greatly improves the response when selecting multiple items in ListView and TableView. However, in TreeView / TreeTableView, the improvement effect is hidden mainly due to the design problem of the cache of TreeUtil.getTreeItem (). Reference value of the number of data that can be handled within 3 seconds of processing time (before-> after) ListView * selectAll: 400_000-> 10_000_000 * selectRange: 7_000-> 70_000 TableView * selectAll: 8_000-> 700_000 * selectRange: 7_000-> 50_000 You can see performance improvements in the following applications: ``` SelectListViewTest.java import javafx.application.Application; import javafx.collections.ObservableList; import javafx.scene.Scene; import javafx.scene.control.Button; import javafx.scene.control.ListView; import javafx.scene.control.SelectionMode; import javafx.scene.layout.BorderPane; import javafx.scene.layout.VBox; import javafx.stage.Stage; public class SelectListViewTest extends Application { final int ROW_COUNT = 70_000; // final int ROW_COUNT = 400_000; // final int ROW_COUNT = 10_000_000; // final int ROW_COUNT = 7_000; @Override public void start(Stage stage) { ListView<String> listView = new ListView<>(); listView.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE); ObservableList<String> items = listView.getItems(); for(int i=0; i<ROW_COUNT; i++) { String rec = String.valueOf(i); items.add(rec); } BorderPane root = new BorderPane(listView); Button selectAll = new Button("selectAll"); Button clearSelection = new Button("clearSelection"); Button selectToStart = new Button("selectToStart"); Button selectToEnd = new Button("selectToEnd"); Button selectPrevious = new Button("selectPrevious"); Button selectNext= new Button("selectNext"); selectAll.setFocusTraversable(true); clearSelection.setFocusTraversable(true); selectToStart.setFocusTraversable(true); selectToEnd.setFocusTraversable(true); selectPrevious.setFocusTraversable(true); selectNext.setFocusTraversable(true); root.setRight(new VBox(6, selectAll, selectToStart, selectToEnd, selectPrevious, selectNext, clearSelection)); stage.setScene(new Scene(root, 600, 600)); selectAll.setOnAction((e)->selectAll(listView)); clearSelection.setOnAction((e)->clearSelection(listView)); selectToStart.setOnAction((e)->selectToStart(listView)); selectToEnd.setOnAction((e)->selectToLast(listView)); selectPrevious.setOnAction((e)->selectPrevious(listView)); selectNext.setOnAction((e)->selectNext(listView)); stage.show(); } private void selectAll(ListView listView) { long t = System.currentTimeMillis(); listView.getSelectionModel().selectAll(); System.out.println("time:"+ (System.currentTimeMillis() - t)); } private void clearSelection(ListView listView) { long t = System.currentTimeMillis(); listView.getSelectionModel().clearSelection(); System.out.println("time:"+ (System.currentTimeMillis() - t)); } private void selectToStart(ListView listView) { long t = System.currentTimeMillis(); listView.getSelectionModel().selectRange(0, listView.getSelectionModel().getSelectedIndex()); System.out.println("time:"+ (System.currentTimeMillis() - t)); } private void selectToLast(ListView listView) { long t = System.currentTimeMillis(); listView.getSelectionModel().selectRange(listView.getSelectionModel().getSelectedIndex(), listView.getItems().size()); System.out.println("time:"+ (System.currentTimeMillis() - t)); } private void selectPrevious(ListView listView) { long t = System.currentTimeMillis(); listView.getSelectionModel().selectPrevious(); System.out.println("time:"+ (System.currentTimeMillis() - t)); } private void selectNext(ListView listView) { long t = System.currentTimeMillis(); listView.getSelectionModel().selectNext(); System.out.println("time:"+ (System.currentTimeMillis() - t)); } public static void main(String[] args) { Application.launch(args); } } ``` SelectTableViewTest.java import javafx.application.Application; import javafx.beans.property.SimpleStringProperty; import javafx.collections.ObservableList; import javafx.scene.Scene; import javafx.scene.control.Button; import javafx.scene.control.SelectionMode; import javafx.scene.control.TableColumn; import javafx.scene.control.TableView; import javafx.scene.layout.BorderPane; import javafx.scene.layout.VBox; import javafx.stage.Stage; public class SelectTableViewTest extends Application { final int ROW_COUNT = 700_000; // final int ROW_COUNT = 80_000; // final int ROW_COUNT = 50_000; // final int ROW_COUNT = 8_000; final int COL_COUNT = 3; @Override public void start(Stage stage) { TableView<String[]> tableView = new TableView<>(); tableView.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE); // tableView.getSelectionModel().setSelectionMode(SelectionMode.SINGLE); final ObservableList<TableColumn<String[], ?>> columns = tableView.getColumns(); for(int i=0; i<COL_COUNT; i++) { TableColumn<String[], String> column = new TableColumn<>("Col"+i); final int colIndex=i; column.setCellValueFactory((cell)->new SimpleStringProperty(cell.getValue()[colIndex])); column.setPrefWidth(150); columns.add(column); } ObservableList<String[]> items = tableView.getItems(); for(int i=0; i<ROW_COUNT; i++) { String[] rec = new String[COL_COUNT]; for(int j=0; j<rec.length; j++) { rec[j] = i+":"+j; } items.add(rec); } BorderPane root = new BorderPane(tableView); Button selectAll = new Button("selectAll"); Button clearSelection = new Button("clearSelection"); Button selectToStart = new Button("selectToStart"); Button selectToEnd = new Button("selectToEnd"); Button selectPrevious = new Button("selectPrevious"); Button selectNext= new Button("selectNext"); selectAll.setFocusTraversable(true); clearSelection.setFocusTraversable(true); selectToStart.setFocusTraversable(true); selectToEnd.setFocusTraversable(true); selectPrevious.setFocusTraversable(true); selectNext.setFocusTraversable(true); root.setRight(new VBox(6, selectAll, selectToStart, selectToEnd, selectPrevious, selectNext, clearSelection)); stage.setScene(new Scene(root, 600, 600)); selectAll.setOnAction((e)->selectAll(tableView)); clearSelection.setOnAction((e)->clearSelection(tableView)); selectToStart.setOnAction((e)->selectToStart(tableView)); selectToEnd.setOnAction((e)->selectToLast(tableView)); selectPrevious.setOnAction((e)->selectPrevious(tableView)); selectNext.setOnAction((e)->selectNext(tableView)); stage.show(); } private void selectAll(TableView tableView) { long t = System.currentTimeMillis(); tableView.getSelectionModel().selectAll(); System.out.println("time:"+ (System.currentTimeMillis() - t)); } private void clearSelection(TableView tableView) { long t = System.currentTimeMillis(); tableView.getSelectionModel().clearSelection(); System.out.println("time:"+ (System.currentTimeMillis() - t)); } private void selectToStart(TableView tableView) { long t = System.currentTimeMillis(); tableView.getSelectionModel().selectRange(0, tableView.getSelectionModel().getFocusedIndex()); System.out.println("time:"+ (System.currentTimeMillis() - t)); } private void selectToLast(TableView tableView) { long t = System.currentTimeMillis(); tableView.getSelectionModel().selectRange(tableView.getSelectionModel().getFocusedIndex(), tableView.getItems().size()); System.out.println("time:"+ (System.currentTimeMillis() - t)); } private void selectPrevious(TableView tableView) { long t = System.currentTimeMillis(); tableView.getSelectionModel().selectPrevious(); System.out.println("time:"+ (System.currentTimeMillis() - t)); } private void selectNext(TableView tableView) { long t = System.currentTimeMillis(); tableView.getSelectionModel().selectNext(); System.out.println("time:"+ (System.currentTimeMillis() - t)); } public static void main(String[] args) { Application.launch(args); } } ------------- Commit messages: - 8197991: Fix multi-select performance issues - 8197991: Fix multi-select performance issues Changes: https://git.openjdk.java.net/jfx/pull/127/files Webrev: https://webrevs.openjdk.java.net/?repo=jfx&pr=127&range=00 Issue: https://bugs.openjdk.java.net/browse/JDK-8197991 Stats: 58 lines in 2 files changed: 50 ins; 0 del; 8 mod Patch: https://git.openjdk.java.net/jfx/pull/127.diff Fetch: git fetch https://git.openjdk.java.net/jfx pull/127/head:pull/127 PR: https://git.openjdk.java.net/jfx/pull/127