使用Java 8流过滤包含来自另一个列表中的一个或多个字符串的字符串列表 [英] Filter a list of strings which contains one or more strings from another list with Java 8 streams

查看:1646
本文介绍了使用Java 8流过滤包含来自另一个列表中的一个或多个字符串的字符串列表的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I want to use the strings imputed in a TextField to filter a list. I am using a KeyReleased Event on the TextField to filter the list on every key. The piece of code below filters the list when I type in a word, but when I press space and start typing another word the list gets empty. I am a bit new to streams. I don't know what I am doing wrong.

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);
    }

}


推荐答案

我无法在您的Stream代码中看到根本问题。你编写它的方式不是很有效,它允许在结果列表中多次出现匹配多个单词的元素。也许,你设置结果的UI无法解决这个问题。

I can’t see a fundamental problem in your Stream code. The way, you’ve written it, is not very efficient and it allows elements matching multiple words to occur multiple times in the result list. Perhaps, the UI you’re setting the result on can’t handle this.

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

I’d create a single filter out of the entered text, which will match if any of the words appears in the element, using a case insensitive matching instead of repeatedly converting every string to lowercase. E.g. with a utility method like this:

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());

这篇关于使用Java 8流过滤包含来自另一个列表中的一个或多个字符串的字符串列表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆