使用Java 8流过滤包含另一个列表中一个或多个字符串的字符串列表

时间:2019-02-15 13:49:29

标签: java regex java-8 java-stream

我想使用在TextField中插入的字符串来过滤列表。我在TextField上使用KeyReleased事件来过滤每个键上的列表。当我输入一个单词时,下面的代码过滤列表,但是当我按下空格键并开始输入另一个单词时,列表变为空。我对流媒体有点陌生。我不知道我在做什么错。


private ObservableList<Products_Data> productList;
@FXML       
private JFXTextField searchField;
@FXML       
private TableView<Products_Data> productTable;
@FXML
void searchKeyReleased(KeyEvent event) {
    String searchText = searchField.getText();
    List<String> searchableWords = Arrays.asList(searchText.toLowerCase().trim().split("\\s+"));
    List<Products_Data> filteredList =  searchableWords.stream()
        .flatMap(i ->productList.stream()
        .filter(j -> j.getPartDesc().toLowerCase().contains(i)))
        .collect(Collectors.toList());
    ObservableList<Products_Data> productFilteredList = FXCollections.observableArrayList(filteredList);
    productTable.setItems(productFilteredList);
}

----------
public class Products_Data {
    private final StringProperty partDesc = new (this,"PartDesc",null);

    public Products_Data() {}

    public final StringProperty getPartDescProperty() {return partDesc;}
    public final String getPartDesc(){return partDesc.get();}
    public final void setPartDesc(String partDesc) {     
        getPartDescProperty().set(partDesc);
    }

}

2 个答案:

答案 0 :(得分:3)

我看不到您的Stream代码中的根本问题。您编写的方式效率不高,并且允许匹配多个单词的元素在结果列表中多次出现。也许,您要在其中设置结果的用户界面无法处理此问题。

我要从输入的文本中创建一个过滤器,使用任何不区分大小写的匹配方式,而不是将每个字符串重复转换为小写字母,从而在元素中出现任何单词时进行匹配。例如。使用这样的实用方法:

static final Pattern SPACE = Pattern.compile("\\s+");

public static <T> Predicate<T> getFilter(Function<? super T, String> f, String words) {
    String regex = SPACE.splitAsStream(words)
        .map(Pattern::quote).collect(Collectors.joining("|"));
    Predicate<String> sp = Pattern.compile(regex, Pattern.CASE_INSENSITIVE).asPredicate();
    return t -> sp.test(f.apply(t));
}

可以用作

List<Products_Data> filteredList = productList.stream()
    .filter(getFilter(Products_Data::getPartDesc, searchField.getText()))
    .collect(Collectors.toList());

答案 1 :(得分:0)

匹配的核心应该是这样的:

productList.stream().filter(
    product -> searchableWords.stream().allMatch(
        searchWord -> product.getPartDesc().toLowerCase().contains(searchWord)
    )
)