Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/314.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 从hashmap中查找具有可变数量属性(一个或多个)的对象_Java_Reflection_Compare - Fatal编程技术网

Java 从hashmap中查找具有可变数量属性(一个或多个)的对象

Java 从hashmap中查找具有可变数量属性(一个或多个)的对象,java,reflection,compare,Java,Reflection,Compare,假设我们有person类: class Person{ long id; String username; String password String firstName; String lastName; String address; String phoneNumber; // setters and getters.. } 我们有一个hashmap,其中包含personhashmap类型的对象,字符串是对象的用户名 我想搜索具有指定属性的对象(一个或多个),例如: 用户名:jim5

假设我们有person类:

class Person{
long id;
String username;
String password
String firstName;
String lastName;
String address;
String phoneNumber;

// setters and getters..
}
我们有一个hashmap,其中包含person
hashmap
类型的对象,字符串是对象的用户名

我想搜索具有指定属性的对象(一个或多个),例如:

用户名:jim54地址:英国

名:吉米,姓:托纳伯恩,地址:波兰

居住在英国的人(地址:英国)

没有编写大量重载方法

我的方法使用反射来查找单个属性的变体:

 Method getter=getDeclaredMethodIgnoreCase(Person.class,"get"+"attribute"); 
 Method setter=getDeclaredMethodIgnoreCase(Person.class,"set"+"attribute");

然后比较并更改

首先,按用户名进行查找

简单地做:

Map<String,Person> people = new HashMap<>();

Person person = people.get("jim54");
例如,查找名为
John
(忽略大小写)和姓为
tornabone
(也忽略大小写)的所有人,地址包含
Poland
字符串(也忽略大小写):

第一个方法接收一个函数,该函数从对象中提取属性,然后根据该属性检查条件。第二种方法简单地将所有给定的谓词合并成一个谓词,从而简化它们

现在可以使用第一种方法,如下所示:

Predicate<Person> condition = SearchUtils.extractThenFilter(
        Person::getAddress, 
        address -> address.toLowerCase().contains("uk"));

List<Person> matching = people.values().stream()
    .filter(condition)
    .collect(Collectors.toList());
Predicate condition=SearchUtils.extractThenFilter(
Person::getAddress,
address->address.toLowerCase().contains(“uk”);
列表匹配=people.values().stream()
.过滤器(条件)
.collect(Collectors.toList());
这相当于上面的第一次搜索

以下内容相当于上述第二次搜索:

Predicate<Person> condition = SearchUtils.and(
        SearchUtils.extractThenFilter(
            Person::getFirstName, 
            str -> "John".equalsIgnoreCase(str)),
        SearchUtils.extractThenFilter(
            Person::getLastName, 
            "tornabone"::equalsIgnoreCase), // just another way
        SearchUtils.extractThenFilter(
            Person::getAddress, 
            str -> str.toLowerCase().contains("poland")));

List<Person> matching = people.values().stream()
    .filter(condition)
    .collect(Collectors.toList());
Predicate condition=SearchUtils.and(
SearchUtils.extractThenFilter(
Person::getFirstName,
str->“John”。等信号情况(str)),
SearchUtils.extractThenFilter(
Person::getLastName,
“tornabone”::equalsIgnoreCase),//另一种方式
SearchUtils.extractThenFilter(
Person::getAddress,
str->str.toLowerCase().contains(“波兰”);
列表匹配=people.values().stream()
.过滤器(条件)
.collect(Collectors.toList());
正如您所看到的,现在,对于两种不同的搜索,以完全相同的方式对映射值进行流式处理、对复合条件进行过滤以及收集到列表。我们已经将不同搜索的复杂性抽象为一个谓词

现在,如果您有一个将属性名称与属性提取器函数相匹配的映射,以及一些接收字符串并创建不同谓词的帮助器方法(例如,一个用于检查给定字符串是否包含在另一个字符串中,另一个用于检查是否忽略大小写相等,等等),然后您只需要解析搜索字符串,就可以完成了

编辑:

该接口是在Java8中引入的。它是一个函数接口,这意味着lambda表达式和方法引用可以针对它

在这里,我使用了例如
Person::getAddress
作为一个函数,将
Person
的实例转换为其地址。在
extractThenFilter
实用程序方法中调用
extractor.apply(t)
时,会调用
Person.getAddress
方法,其中
t
Person
类的实例。然后,从
Person
实例中提取的地址被传递给谓词(条件)。由于提取的地址类型为
String
,因此give谓词接收该字符串并检查其是否满足条件(以下是同一示例,它检查
Person
类小写字母实例的提取地址是否包含
“uk”


您可以查看和以供进一步参考。

您能否提供一些关于在通用方法中使用“函数”接口的参考?我还是不完全明白it@user2962142
java.util.function.function
是在Java8中引入的。它是一个函数接口,这意味着lambda表达式和方法引用可以针对它。在这里,我使用了例如
Person::getAddress
作为一个函数,将
Person
的实例转换为其地址。您可以查看和以获得进一步的参考。@user2962142我已经添加了一些解释。希望现在更清楚了。我建议您阅读本教程、javadocs以及其他关于函数和谓词的问题!这是你付出的巨大努力,学到了很多,尽管它仍然不能解决不知道要检查的属性的想法,因为用户提供了一个包含属性的字符串,即“地址”,所以我不能像Person::get+“Address”或其他什么样,但总的来说,你的回答很棒@用户2962142不客气!但是,你知道,从例如
“address”
Person::getAddress
非常简单:你所需要的只是一张
地图。您可以这样填充它:
map.put(“address”,Person::getAddress)
,等等。然后,您只需在映射上使用get:
函数提取器=map.get(“address”)
public static <T, S> Predicate<T> extractThenFilter(
        Function<T, S> extractor, 
        Predicate<S> condition) {

    return t -> condition.test(extractor.apply(t));
}

public static <T> Predicate<T> and(Predicate<T>... conditions) {
    return Arrays.stream(conditions)
        .reduce(Predicate::and)
        .orElse(t -> true);
}
Predicate<Person> condition = SearchUtils.extractThenFilter(
        Person::getAddress, 
        address -> address.toLowerCase().contains("uk"));

List<Person> matching = people.values().stream()
    .filter(condition)
    .collect(Collectors.toList());
Predicate<Person> condition = SearchUtils.and(
        SearchUtils.extractThenFilter(
            Person::getFirstName, 
            str -> "John".equalsIgnoreCase(str)),
        SearchUtils.extractThenFilter(
            Person::getLastName, 
            "tornabone"::equalsIgnoreCase), // just another way
        SearchUtils.extractThenFilter(
            Person::getAddress, 
            str -> str.toLowerCase().contains("poland")));

List<Person> matching = people.values().stream()
    .filter(condition)
    .collect(Collectors.toList());