title: JavaFX Tableview with FilteredList (JDK 8) does not sort by column
body: <p>I was playing around with the <code>FilteredList</code> class they have added back in to JDK8 and it feels a lot faster - appears to give performance closer to GlazedLists.  However table column sorting does not seem to work at all when I use a <code>FilteredList</code> instead of a <code>ObservableList</code>.  </p>
  
  <p>There are no exceptions / stacktrace in the console.</p>
  
  <p>Here are my instance members in my controller:        </p>
  
  <pre><code>    private ObservableList&lt;Film&gt; masterData = FXCollections.observableArrayList();
      private FilteredList&lt;Film&gt; filteredData;
  </code></pre>
  
  <p>My controller init:</p>
  
  <pre><code>@FXML
  void initialize() {
     ...   
     filmTable.setItems(filteredData);
     ...
  }
  </code></pre>
  
  <p>Constructor:</p>
  
  <pre><code>public FilmBrowserController() {
  
     ...
     masterData.addAll(filmRepository.findAllSortedByTitle());
     filteredData = new FilteredList&lt;&gt;(masterData);
     filteredData.setPredicate(film -&gt; true);
  }
  </code></pre>
  
  <p>I have been filtering the list by just setting a new predicate when a filter TextField is changed:</p>
  
  <pre><code>filteredData.setPredicate(film -&gt;
       film.getTitle().toLowerCase().contains(filterField.getText().toLowerCase()));
  </code></pre>
  
  <p>I am pretty green to JavaFX still - am I missing something pretty basic or is this likely to be a bug?  I am using the JDK 8 downloaded here: <a href="https://jdk8.java.net/download.html" rel="noreferrer">https://jdk8.java.net/download.html</a> Build b100. </p>
  
  <p>Is it not possible to have a table which can be filtered but sorted by column at the same time?</p>
  
  <p>edit: </p>
  
  <p>Modified another javaFX table sample I found on stackoverflow, I added this line (74):</p>
  
  <pre><code>table.setItems(table.getItems().filtered(p -&gt; p.getFirstName().startsWith("a")));
  </code></pre>
  
  <p>The full source:</p>
  
  <pre><code>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.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.StackPane;
  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 final int INIT_LIST_SIZE = 100_000;
  
      @Override
      public void start(Stage stage) {
          Scene scene = new Scene(new StackPane());
          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&lt;Person&gt; table = new TableView&lt;Person&gt;();
          table.setEditable(true);
  
          TableColumn&lt;Person, String&gt; firstNameCol = new TableColumn&lt;Person, String&gt;("First Name");
          firstNameCol.setMinWidth(100);
          firstNameCol.setCellValueFactory(
                  new PropertyValueFactory&lt;Person, String&gt;("firstName"));
          firstNameCol.setCellValueFactory(new Callback&lt;TableColumn.CellDataFeatures&lt;Person,String&gt;, ObservableValue&lt;String&gt;&gt;() {
              @Override
              public ObservableValue&lt;String&gt; call(CellDataFeatures&lt;Person, String&gt; cdf) {
                  return cdf.getValue().firstNameProperty();
              }
          });
  
          TableColumn&lt;Person, String&gt; lastNameCol = new TableColumn&lt;Person, String&gt;("Last Name");
          lastNameCol.setMinWidth(100);
          lastNameCol.setCellValueFactory(
                  new PropertyValueFactory&lt;Person, String&gt;("lastName"));
  
  
  
          TableColumn&lt;Person, String&gt; emailCol = new TableColumn&lt;Person, String&gt;("Email");
          emailCol.setMinWidth(200);
          emailCol.setCellValueFactory(
                  new PropertyValueFactory&lt;Person, String&gt;("email"));
  
  
  
          final Random random = new Random();
          for (int i = 0; i &lt; INIT_LIST_SIZE; i++) {
              table.getItems().add(new Person(randomString(random), randomString(random), randomString(random)));
          }
          table.getColumns().addAll(Arrays.asList(firstNameCol, lastNameCol, emailCol));
  
          table.setItems(table.getItems().filtered(p -&gt; p.getFirstName().startsWith("a")));
  
          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&lt;ActionEvent&gt;() {
              @Override
              public void handle(ActionEvent e) {
                  String firstName = isEmpty(addFirstName.getText()) ? randomString(random) : addFirstName.getText();
                  String lastName  = isEmpty(addLastName.getText())  ? randomString(random) : addLastName.getText();
                  String email     = isEmpty(addEmail.getText())     ? randomString(random) : addEmail.getText();
                  Person person = new Person(firstName, lastName, email);
                  int idx = Collections.binarySearch(table.getItems(), person);
                  if (idx &lt; 0) {
                      idx = -idx - 1;
                  }
                  table.getItems().add(idx, person);
                  table.getSelectionModel().select(idx);
                  table.scrollTo(idx);
  
                  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));
          vbox.getChildren().addAll(label, table, hb);
  
          ((StackPane) scene.getRoot()).getChildren().addAll(vbox);
  
          stage.setScene(scene);
          stage.show();
      }
  
      public static void main(String[] args) {
          launch(args);
      }
  
      private boolean isEmpty(String string) {
          return (string == null || string.isEmpty());
      }
  
      private String randomString(Random random) {
          char[] chars = new char[20];
          for (int i = 0; i &lt; 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&lt;Person&gt; {
  
          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().compareToIgnoreCase(o.getFirstName());
          }
      }
  }
  </code></pre>
  
  <p>I have now created a ticket for this <a href="https://javafx-jira.kenai.com/browse/RT-32091" rel="noreferrer">https://javafx-jira.kenai.com/browse/RT-32091</a></p>