使用Java 8 streams从另一个列表中筛选包含一个或多个字符串的字符串列表

使用Java 8 streams从另一个列表中筛选包含一个或多个字符串的字符串列表,java,regex,java-8,java-stream,Java,Regex,Java 8,Java Stream,我想使用文本字段中输入的字符串来过滤列表。我使用TextField上的KeyReleased事件来过滤每个键上的列表。当我键入一个单词时,下面的代码会过滤列表,但当我按空格键并开始键入另一个单词时,列表将变为空。我对streams有点陌生。我不知道我做错了什么 私有可观察列表产品列表; @FXML 私有JFXTextField搜索字段; @FXML 私有TableView产品表; @FXML 作废searchKeyReleased(KeyEvent事件){ String searchText=

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


私有可观察列表产品列表;
@FXML
私有JFXTextField搜索字段;
@FXML
私有TableView产品表;
@FXML
作废searchKeyReleased(KeyEvent事件){
String searchText=searchField.getText();
List searchableWords=Arrays.asList(searchText.toLowerCase().trim().split(“\\s+”);
List filteredList=searchableWords.stream()
.flatMap(i->productList.stream()
.filter(j->j.getPartDesc().toLowerCase().contains(i)))
.collect(Collectors.toList());
ObservableList productFilteredList=FXCollections.observableArrayList(filteredList);
productTable.setItems(productFilteredList);
}
----------
公共类产品\u数据{
私有最终StringProperty partDesc=new(此“partDesc”,null);
公共产品_Data(){}
公共最终StringProperty getPartDescProperty(){return partDesc;}
公共最终字符串getPartDesc(){return partDesc.get();}
公共最终void setPartDesc(字符串partDesc){
getPartDescProperty().set(partDesc);
}
}

匹配的核心应该是:

productList.stream().filter(
    product -> searchableWords.stream().allMatch(
        searchWord -> product.getPartDesc().toLowerCase().contains(searchWord)
    )
)
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));
}

我看不出你的流代码有什么根本问题。您编写的方法不是很有效,它允许匹配多个单词的元素在结果列表中多次出现。也许,您正在设置结果的UI无法处理此问题

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

productList.stream().filter(
    product -> searchableWords.stream().allMatch(
        searchWord -> product.getPartDesc().toLowerCase().contains(searchWord)
    )
)
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));
}
static final Pattern SPACE=Pattern.compile(\\s+);

公共静态谓词getFilter(函数尝试测试在
数组.asList(searchText.toLowerCase().trim().split(\\s+));
使用您的输入并进一步使用这些属性满足
.getPartDesc().toLowerCase().contains(i)
之后得到什么?什么是
新的(这个“PartDesc”,null)
do?这不可能是您的工作代码。为什么要将
searchField.getText()返回的文本用
String.valueOf(…)包装起来
。以编写流代码的方式,同一项可以多次出现。无论
productTable
是什么,如果可搜索集很小(且不同),是否可以处理这种情况,然后我会亲自制作一个输入单词的
HashSet
,以及一个可搜索单词的
LinkedHashSet
。然后从可搜索集的副本中删除输入。内存效率较低,但计算速度应该更快。