Вопрос от опытного программиста, который все еще относительно новичок в Java.
Я создал прототип класса, который добавляет Excel-подобные фильтры данных к столбцам в TableView
.Сейчас я делаю его универсальным, чтобы он работал с любым TableView
, и я застрял с тем, как "обобщить" создание Predicate
s.
в моем прототипе (где язакодировал все), я вызываю метод createPredicate()
для String
столбца «Значение», например, так:
createPredicate(TableViewModel::getTvValue);
, а в методе createPredicate()
я устанавливаю Predicate
как это:
private void createPredicate(Function<TableViewModel, String> columnGetter) {
//...
final String filter = "some value";
Predicate<TableViewModel> predicate = tvm -> columnGetter.apply(tvm).contains(filter);
//...
}
Как я могу сделать как вызов метода, так и сам метод универсальным, чтобы они работали для любого TableColumn
?
Я застрял вдва места.Во-первых, как получить геттер для TableColumn
, чтобы я мог передать его методу createPredicate()
...
//Get a column
TableColumn<S, T> col = (TableColumn<S, T>) table.getColumns().get(0);
//Set a predicate based on the column
//==>STUCK HERE: How do I get the getter for the column?
createPredicate(S::<WHAT_GOES_HERE?>);
... и во-вторых, как сделать универсальный contains()
.В настоящее время я получаю сообщение об ошибке «Не удается найти метод символа содержит (T)».
private void createPredicate(Function<S, T> columnGetter) {
final T filter = (T) "some value";
//STUCK HERE: How to genericise the contains?
Predicate<S> predicate = tvm -> columnGetter.apply(tvm).contains(filter);
}
Заранее спасибо.Если это поможет, вот MVCE.Я использую JavaFX8 (JDK1.8.0_181) и NetBeans 8.2.
(голые кости!) TestColumnFilter.java класс:
import java.util.function.Function;
import java.util.function.Predicate;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
public class TestColumnFilter<S, T> {
public TestColumnFilter(TableView<S> table) {
//Get a column
TableColumn<S, T> col = (TableColumn<S, T>) table.getColumns().get(0);
//Set a predicate based on the column
//STUCK HERE: How to get the getter for the column?
createPredicate(S::<WHAT_GOES_HERE?>);
}
private void createPredicate(Function<S, T> columnGetter) {
final T filter = (T) "some value";
//STUCK HERE: How to genericise the contains?
//Currently getting a "cannot find symbol method contains(T)" compiler error
Predicate<S> predicate = tvm -> columnGetter.apply(tvm).contains(filter);
}
public static <S, T> TestColumnFilter<S, T> createColumnFiltersForTableView(TableView<S> table) {
return new TestColumnFilter<>(table);
}
}
и Test55.java , фиктивный класс, который использует TestColumnFilter.java.
import java.util.Arrays;
import javafx.application.Application;
import static javafx.application.Application.launch;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
public class Test55 extends Application {
private Parent createContent() {
TableView<TableViewModel> table = new TableView<>();
TableColumn<TableViewModel, String> valueCol = new TableColumn<>("Value");
valueCol.setCellValueFactory(cb -> cb.getValue().tvValueProperty());
table.getColumns().addAll(Arrays.asList(valueCol));
TestColumnFilter.createColumnFiltersForTableView(table);
BorderPane content = new BorderPane(table);
return content;
}
private class TableViewModel {
private final StringProperty tvValue;
public TableViewModel(
String tvValue
) {
this.tvValue = new SimpleStringProperty(tvValue);
}
public String getTvValue() {return tvValue.get().trim();}
public void setTvValue(String tvValue) {this.tvValue.set(tvValue);}
public StringProperty tvValueProperty() {return tvValue;}
}
@Override
public void start(Stage stage) throws Exception {
stage.setScene(new Scene(createContent()));
stage.setTitle("Test");
stage.show();
}
public static void main(String[] args) {
launch(args);
}
}