El tipo de tabla de JavaFx es realmente lento para mejorar la velocidad de clasificación como en el swing de Java

Estoy trabajando en la aplicación javaFx y he creado una tabla vista y tengo más de 100.000 filas con 10 columnas.

También creé la misma mesa usando java swing Jtable.

Ahora necesito ordenar el rendimiento para que sea mejor en javaFx, si no es mejor que algo que esté cerca de jtable de java swing.

Ahora mismo estoy usando sortorder (), que ordena los datos al hacer clic en los encabezados de las columnas y ordenar la velocidad es 20 veces más lento que Jtable.

Alguien puede ayudarme porfavor ?

Gracias

Editar:

Estoy usando el ejemplo 13.8 en este enlace http://docs.oracle.com/javafx/2/ui_controls/table-view.htm acaba de agregar algunas líneas de código para simplemente agregar 100.000 filas mediante la generación de datos aleatorios.

Me tomó un tiempo, pero creo que lo he descubierto, al menos para este ejemplo.

En este ejemplo, la clase Persona no tiene acceso a propiedades (es decir, hay un método getFirstName (), pero no el método firstNameProperty ()). La ordenación por columnas tiene que acceder al valor en cada celda de la columna mediante la fábrica de valores de celda. Cuando no hay acceso a la propiedad, la fábrica del valor de la celda va a llamar a getFirstName () y luego ajusta el resultado en un nuevo ReadOnlyObjectWrapper en cada invocación.

Si se asegura de que la clase que representa los datos de fila tenga los descriptores de acceso de propiedad adecuados, entonces recuperar el valor es mucho más eficiente, ya que simplemente devuelve una referencia a StringProperty existente.

Este ejemplo ordena 100.000 filas en aproximadamente un segundo en mi sistema (MacBookPro 8GB RAM, quad core). Puede mejorar más el rendimiento al proporcionar una fábrica de valor de celda explícita, lo que evita la necesidad de reflexión al calcular el valor de la celda. En otras palabras, reemplazar

firstNameCol.setCellValueFactory( new PropertyValueFactory("firstName")); 

con

  firstNameCol.setCellValueFactory(new Callback, ObservableValue>() { @Override public ObservableValue call(CellDataFeatures cdf) { return cdf.getValue().firstNameProperty(); } }); 

El ahorro de rendimiento aquí no es tan dramático.

Aquí está el ejemplo completo:

 import javafx.application.Application; import javafx.beans.property.SimpleStringProperty; import javafx.beans.property.StringProperty; import javafx.beans.value.ObservableValue; 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.TableColumn.CellDataFeatures; 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 javafx.util.Callback; import java.util.Arrays; import java.util.Collections; import java.util.Date; import java.util.Random; public class TableSortPerformanceTest extends Application { 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)); final TableView table = new TableView(); table.setEditable(true); TableColumn firstNameCol = new TableColumn("First Name"); firstNameCol.setMinWidth(100); firstNameCol.setCellValueFactory( new PropertyValueFactory("firstName")); firstNameCol.setCellValueFactory(new Callback, ObservableValue>() { @Override public ObservableValue call(CellDataFeatures cdf) { return cdf.getValue().firstNameProperty(); } }); TableColumn lastNameCol = new TableColumn("Last Name"); lastNameCol.setMinWidth(100); lastNameCol.setCellValueFactory( new PropertyValueFactory("lastName")); TableColumn emailCol = new TableColumn("Email"); emailCol.setMinWidth(200); emailCol.setCellValueFactory( new PropertyValueFactory("email")); Random random = new Random(); for (int i = 0; i < 100000; i++) { table.getItems().add(new Person(randomString(random), randomString(random), randomString(random))); } table.getColumns().addAll(Arrays.asList(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() { @Override public void handle(ActionEvent e) { table.getItems().add(new Person( addFirstName.getText(), addLastName.getText(), addEmail.getText())); addFirstName.clear(); addLastName.clear(); addEmail.clear(); } }); final HBox hb = new HBox(3); hb.getChildren().addAll(addFirstName, addLastName, addEmail, addButton); 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 { private final StringProperty firstName; private final StringProperty lastName; private final StringProperty 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 StringProperty firstNameProperty() { return firstName ; } public String getLastName() { return lastName.get(); } public void setLastName(String fName) { lastName.set(fName); } public StringProperty lastNameProperty() { return lastName ; } public String getEmail() { return email.get(); } public void setEmail(String fName) { email.set(fName); } public StringProperty emailProperty() { return email ; } @Override public int compareTo(Person o) { return firstName.get().compareTo(o.getFirstName()); } } } 

ACTUALIZACIÓN: tenga en cuenta que esto se soluciona en JavaFX 8.

No sé qué pasa con la velocidad del tipo en TableView cuando haces clic en el encabezado de la tabla: se hace lento con 100,000 filas como mencionas en tu pregunta.

Si solo proporciona un botón que ordena la colección subyacente, ordena mucho más rápido y la tabla se actualiza correctamente (al menos en Java 8). El tiempo para ordenar una columna fue muy inferior a un segundo.

 Button sortByEmail = new Button("Sort by Email"); sortByEmail.setOnAction(new EventHandler() { @Override public void handle(ActionEvent event) { Collections.sort(table.getItems(), new Comparator() @Override public int compare(Person o1, Person o2) { return o1.getEmail().compareTo(o2.getEmail()); } }); } }); 

O usando Java 8 lambdas:

 Button sortByEmail = new Button("Sort by Email"); sortByEmail.setOnAction(event -> Collections.sort( table.getItems(), (o1, o2) -> o1.getEmail().compareTo(o2.getEmail()) ) ); 

Por lo tanto, si tiene muchos elementos en su tabla, en la columna llame a setSortable (falso) y proporcione botones para que el usuario ordene las columnas de la tabla si es necesario.

Al conectar mi computadora portátil a la pared y boost la memoria máxima de la JVM también aumentó el rendimiento de clasificación para grandes conjuntos de datos (reduciendo el tiempo para ordenar haciendo clic en el encabezado de una columna con la muestra de 20 segundos a 10 segundos).

Archive una solicitud de mejora contra el rastreador de problemas JavaFX con el siguiente código de ejemplo. El código genera 100.000 filas de datos aleatorios y puede verificar el rendimiento de la clasificación estándar de columnas haciendo clic en un encabezado de columna de tabla para ordenar en una columna de tabla y compararlo con el rendimiento de ordenar por Collections.sort invocado al presionar botones.

 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 table = new TableView(); private final ObservableList 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("firstName")); TableColumn lastNameCol = new TableColumn("Last Name"); lastNameCol.setMinWidth(100); lastNameCol.setCellValueFactory( new PropertyValueFactory("lastName")); TableColumn emailCol = new TableColumn("Email"); emailCol.setMinWidth(200); emailCol.setCellValueFactory( new PropertyValueFactory("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() { @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() { @Override public void handle(ActionEvent event) { Collections.sort(table.getItems()); } }); Button sortByEmail = new Button("Sort by Email"); sortByEmail.setOnAction(new EventHandler() { @Override public void handle(ActionEvent event) { Collections.sort(table.getItems(), new Comparator() { @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 { 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()); } } }