ObservableList JavaFX 上的多个过滤器

Multiple filters on ObservableList JavaFX

我想知道为一个 ObservableList 对象应用多个过滤器的最佳实现是什么。

我有以下对象:
ComboBox cbYear
文本字段 tfSearch
ObservableList 数据。

我需要根据cbYear的值和tfSearch的值过滤数据列表。

这是我为实现要求所做的工作,但我想知道是否有更简单的方法...

private void initializeFilterTable() {
    
    FilteredList<OrderItem> dataFiltered = new FilteredList<>(data, p -> true);

    tfSearch.textProperty().addListener((obs, oldVal, newVal) -> {
        String year = cbYear.getSelectionModel().getSelectedItem();
        Predicate<OrderItem> filter = filters(newVal, year);
        dataFiltered.setPredicate(filter);
    });
    
    cbYear.getSelectionModel().selectedItemProperty().addListener((obs, oldVal, newVal) -> {
        Predicate<OrderItem> filter = filters(tfSearch.getText(), newVal);
        dataFiltered.setPredicate(filter);
    });
    
    SortedList<OrderItem> dataSorted = new SortedList<>(dataFiltered);
    dataSorted.comparatorProperty().bind(table.comparatorProperty());
    table.setItems(dataSorted);
}



private Predicate<OrderItem> filters(String search, String year) {
    
    String lower = search.trim().toLowerCase();
    
    Predicate<OrderItem> searchFilter = order -> {

        if (lower == null || lower.isEmpty())
            return true;
    
        if (order.getCustomerName().toLowerCase().contains(lower))
            return true;
        else if (order.getOrderNumber().toLowerCase().contains(lower))
            return true;
        else if (order.getPDA_TypeStr().toLowerCase().contains(lower))
            return true;
        else if (order.getCount4UStr().toLowerCase().contains(lower))
            return true;
        else if (order.getCity().toLowerCase().contains(lower))
            return true;
        else if (order.getContactName().toLowerCase().contains(lower))
            return true;
        else if (order.getSoftware().toLowerCase().contains(lower))
            return true;
        else if (order.getPDA_Type() == 2 && "אנדרואיד".contains(lower))
            return true;
        else if (order.getStatusStr().toLowerCase().contains(lower))
            return true;
    
        return false;
    };
    
    
    Predicate<OrderItem> yearFilter = order -> {
        
        if (year.equals("הכל"))
            return true;
        
        else if (year.equals(String.valueOf(order.getYear())))
            return true;
        
        return false;
    };

    return searchFilter.and(yearFilter);
}

您可以过滤已过滤的列表。这使两个逻辑部分分开。

FilteredList<OrderItem> filteredByText = new FilteredList<>(data, p -> true);
FilteredList<OrderItem> filteredByYear = new FilteredList<>(filteredByText, p -> true);

tfSearch.textProperty().addListener((obs, oldVal, newVal) -> filteredByText.setPredicate(p -> {
    String lower = newVal.trim().toLowerCase();
    if (lower == null || lower.isEmpty())
        return true;

    if (order.getCustomerName().toLowerCase().contains(lower))
        return true;
    else if (order.getOrderNumber().toLowerCase().contains(lower))
        return true;
    else if (order.getPDA_TypeStr().toLowerCase().contains(lower))
        return true;
    else if (order.getCount4UStr().toLowerCase().contains(lower))
        return true;
    else if (order.getCity().toLowerCase().contains(lower))
        return true;
    else if (order.getContactName().toLowerCase().contains(lower))
        return true;
    else if (order.getSoftware().toLowerCase().contains(lower))
        return true;
    else if (order.getPDA_Type() == 2 && "אנדרואיד".contains(lower))
        return true;
    else if (order.getStatusStr().toLowerCase().contains(lower))
        return true;

    return false;
}));


cbYear.getSelectionModel().selectedItemProperty().addListener((obs, oldVal, year) -> filteredByYear.setPredicate(p -> {
    if (year.equals("הכל"))
        return true;
    
    else if (year.equals(String.valueOf(order.getYear())))
        return true;
    
    return false;
}));

SortedList<OrderItem> dataSorted = new SortedList<>(filteredByYear);
dataSorted.comparatorProperty().bind(table.comparatorProperty());
table.setItems(dataSorted);