I donβt know what happens with the sorting speed in TableView when you click on the table title - it slows down from 100,000 rows, as you mention in your question.
If you just provide a button that sorts the base collection, it sorts many times faster and the table updates perfectly (at least in Java 8). The column sorting time was significantly lower than a second.
Button sortByEmail = new Button("Sort by Email"); sortByEmail.setOnAction(new EventHandler<ActionEvent>() { @Override public void handle(ActionEvent event) { Collections.sort(table.getItems(), new Comparator<Person>() @Override public int compare(Person o1, Person o2) { return o1.getEmail().compareTo(o2.getEmail()); } }); } });
Or using Java 8 lambdas:
Button sortByEmail = new Button("Sort by Email"); sortByEmail.setOnAction(event -> Collections.sort( table.getItems(), (o1, o2) -> o1.getEmail().compareTo(o2.getEmail()) ) );
So, if there are a lot of elements in your table, setSortable (false) is called in the column and provide buttons for sorting the user by the table columns, if you need to.
Connecting the laptop to the wall and increasing the maximum JVM memory also increased the sorting performance for large data sets (reducing the sorting time by clicking the column heading with a sample below from 20 seconds to 10 seconds).
Submit an extension request to the JavaFX error tracker with the following code sample. The code generates 100,000 rows of random data, and you can check the performance of standard column sorting by clicking the column heading of the table to sort the column of the table and compare this to the sorting performance of Collections.sort called up by clicking the buttons.
import javafx.application.Application; import javafx.beans.property.SimpleStringProperty; import javafx.collections.FXCollections; import javafx.collections.ObservableList; import javafx.event.ActionEvent; import javafx.event.EventHandler; import javafx.geometry.Insets; import javafx.scene.Group; import javafx.scene.Scene; import javafx.scene.control.*; import javafx.scene.control.cell.PropertyValueFactory; import javafx.scene.layout.HBox; import javafx.scene.layout.VBox; import javafx.scene.text.Font; import javafx.stage.Stage; import java.util.Collections; import java.util.Comparator; import java.util.Date; import java.util.Random; public class Test extends Application { private TableView<Person> table = new TableView<Person>(); private final ObservableList<Person> data = FXCollections.observableArrayList( new Person("Jacob", "Smith", " jacob.smith@example.com "), new Person("Isabella", "Johnson", " isabella.johnson@example.com "), new Person("Ethan", "Williams", " ethan.williams@example.com "), new Person("Emma", "Jones", " emma.jones@example.com "), new Person("Michael", "Brown", " michael.brown@example.com ")); final HBox hb = new HBox(); public static void main(String[] args) { launch(args); } @Override public void start(Stage stage) { Scene scene = new Scene(new Group()); stage.setTitle("Table View Sample"); stage.setWidth(550); stage.setHeight(550); final Label label = new Label("Address Book"); label.setFont(new Font("Arial", 20)); table.setEditable(true); TableColumn firstNameCol = new TableColumn("First Name"); firstNameCol.setMinWidth(100); firstNameCol.setCellValueFactory( new PropertyValueFactory<Person, String>("firstName")); TableColumn lastNameCol = new TableColumn("Last Name"); lastNameCol.setMinWidth(100); lastNameCol.setCellValueFactory( new PropertyValueFactory<Person, String>("lastName")); TableColumn emailCol = new TableColumn("Email"); emailCol.setMinWidth(200); emailCol.setCellValueFactory( new PropertyValueFactory<Person, String>("email")); Random random = new Random(); table.setItems(data); for (int i = 0; i < 100000; i++) { table.getItems().add(new Person(randomString(random), randomString(random), randomString(random))); } table.getColumns().addAll(firstNameCol, lastNameCol, emailCol); long start = new Date().getTime(); Collections.sort(table.getItems()); long end = new Date().getTime(); System.out.println("Took: " + (end - start)); final TextField addFirstName = new TextField(); addFirstName.setPromptText("First Name"); addFirstName.setMaxWidth(firstNameCol.getPrefWidth()); final TextField addLastName = new TextField(); addLastName.setMaxWidth(lastNameCol.getPrefWidth()); addLastName.setPromptText("Last Name"); final TextField addEmail = new TextField(); addEmail.setMaxWidth(emailCol.getPrefWidth()); addEmail.setPromptText("Email"); final Button addButton = new Button("Add"); addButton.setOnAction(new EventHandler<ActionEvent>() { @Override public void handle(ActionEvent e) { data.add(new Person( addFirstName.getText(), addLastName.getText(), addEmail.getText())); addFirstName.clear(); addLastName.clear(); addEmail.clear(); } }); Button sortByFirstName = new Button("Sort by First Name"); sortByFirstName.setOnAction(new EventHandler<ActionEvent>() { @Override public void handle(ActionEvent event) { Collections.sort(table.getItems()); } }); Button sortByEmail = new Button("Sort by Email"); sortByEmail.setOnAction(new EventHandler<ActionEvent>() { @Override public void handle(ActionEvent event) { Collections.sort(table.getItems(), new Comparator<Person>() { @Override public int compare(Person o1, Person o2) { return o1.getEmail().compareTo(o2.getEmail()); } }); } }); hb.getChildren().addAll(addFirstName, addLastName, addEmail, addButton, sortByFirstName, sortByEmail); hb.setSpacing(3); final VBox vbox = new VBox(); vbox.setSpacing(5); vbox.setPadding(new Insets(10, 0, 0, 10)); vbox.getChildren().addAll(label, table, hb); ((Group) scene.getRoot()).getChildren().addAll(vbox); stage.setScene(scene); stage.show(); } private String randomString(Random random) { char[] chars = new char[20]; for (int i = 0; i < 20; i++) { int nextInt = random.nextInt(26); nextInt += random.nextBoolean() ? 65 : 97; chars[i] = (char) nextInt; } return new String(chars); } public static class Person implements Comparable<Person> { private final SimpleStringProperty firstName; private final SimpleStringProperty lastName; private final SimpleStringProperty email; private Person(String fName, String lName, String email) { this.firstName = new SimpleStringProperty(fName); this.lastName = new SimpleStringProperty(lName); this.email = new SimpleStringProperty(email); } public String getFirstName() { return firstName.get(); } public void setFirstName(String fName) { firstName.set(fName); } public String getLastName() { return lastName.get(); } public void setLastName(String fName) { lastName.set(fName); } public String getEmail() { return email.get(); } public void setEmail(String fName) { email.set(fName); } @Override public int compareTo(Person o) { return firstName.get().compareTo(o.getFirstName()); } } }