具有任何匹配属性的对象的 JAVA 8 过滤器列表

Posted

技术标签:

【中文标题】具有任何匹配属性的对象的 JAVA 8 过滤器列表【英文标题】:JAVA 8 filter list of object with any matching property 【发布时间】:2020-06-17 16:34:46 【问题描述】:

我的要求是通过匹配任何属性的字符串过滤对象列表。 例如,假设Contact 类具有三个属性:街道、城市、电话。

我知道 java 流过滤器是如何工作的,我必须将输入字符串与每个属性进行比较,如下所示:

contactList.stream().filter(contact -> contact.getStreet().equals("dubai") || 
                            contact.getCity().equals("dubai") || .......).collect(Collectors.toList());

但是,如果一个类有 20 多个属性并且列表大小为 80,000 多个,则将每个属性与输入字符串进行比较会影响性能。所以我的问题是,Java 或任何其他库是否支持使用任何匹配属性过滤列表?如下:

contactList.stream().filter(contact -> contact.anyProperty.equals("dubai").collect(Collectors.toList());

谁能帮帮我,谢谢。

【问题讨论】:

似乎您需要在数据库中进行全文搜索。你考虑过/调查过吗? 没有库可以消除任务所需的基本操作。您想要检查所有属性,您需要检查所有属性。任何更好看的解决方案只会隐藏实际工作。 【参考方案1】:

您可以通过使用反射读取所有类属性来解决此问题

通过重写 toString() 方法并检查 to String 的结果是否包含输入字符串

【讨论】:

谢谢,toString() 将是简单的技巧,我会检查性能。 显然,将 20 多个属性连接到一个字符串中进行搜索,比仅比较 20 多个属性更有效。【参考方案2】:

一种可能的方法是用必需的属性覆盖toString(),并使用它来检查它是否包含单词,

contactList.stream()
    .filter(contact -> contact.toString().contains("dubai"))
    .collect(Collectors.toList());

您可能还想使用Pattern 来匹配确切的单词。

【讨论】:

【参考方案3】:

您可以使用findAny。一旦找到候选人,这将结束:

Optional<Contact> contact = contactList.stream().filter(contact -> contact.getStreet().equals("dubai") || 
                        contact.getCity().equals("dubai") || .......).findAny();

或者,如果您只需要存在此类对象的信息,请使用anyMatch

boolean exists = contactList.stream().anyMatch(contact -> contact.getStreet().equals("dubai") || 
                        contact.getCity().equals("dubai") || .......);

【讨论】:

【参考方案4】:

我有一个项目使用 Gson 和 JSON,当我看到你的问题时,我首先想到的是:

    将您的列表转换为 JsonObject 的 JsonArray => 您可以轻松获取每个 JsonObject 的键集(您的联系人对象的属性列表) 在该列表中过滤,找到所有值为“dubai”的 JsonObject

【讨论】:

您能分享一下如何过滤JsonObjects,并获取过滤后对象的ID 转换为json文本:String json = new Gson().toJson(yourList);转换为json数组:JsonArray arr = new JsonParser().parse(json).getAsJsonArray();JsonArray是一个Iterable,它的元素是JsonElement,可以通过.getAsJsonObject()转换为JsonObject,而JsonObject有“entrySet” ()` 尝试自己使用它们 谢谢,试试这个。【参考方案5】:

我猜,代码阻止你的问题已经解决了。

contactList.stream().anyMatch(contact -> contactMacther(contact,"dubai"));
private boolean contactMacther(Contact contact, String match)
    return contact.getStreet().equalsIgnoreCase(match) ||
            contact.getCity().equalsIgnoreCase(match);

【讨论】:

【参考方案6】:

您可以创建提取属性的函数列表,而不是在您的过滤方法中使用它:

List<Function<Contact, Object>> getPrperties = Arrays.asList(
        Contact::getStreet, 
        Contact::getCity
        // other
        );

contactList.stream()
        .filter(contact -> getPrperties.stream()
                .map(f -> f.apply(contact))
                .anyMatch("dubai"::equals)
        )
        .collect(Collectors.toList();

或者你可以提取测试方法:

BiFunction<Contact, String, Boolean> test = (contact, values) ->
        getPrperties.stream().map(f -> f.apply(contact)).anyMatch(values::equals);

List<Person> collect = contactList.stream()
        .filter(contact -> test.apply(contact, "dubai"))
        .collect(Collectors.toList());

【讨论】:

以上是关于具有任何匹配属性的对象的 JAVA 8 过滤器列表的主要内容,如果未能解决你的问题,请参考以下文章

检查自定义对象列表是不是与 Java 8 中的属性具有相同的值

如何使用underscore.js在列表元素中过滤具有匹配参数的对象?

查找一个列表中具有与另一个对象列表中的属性匹配的属性的所有对象

C#返回具有匹配属性的对象列表[重复]

在对象的 NSArray 中搜索与任何属性匹配的字符串

根据匹配的对象属性从列表创建列表