如何从泛型HashMap获取具有通用条件

时间:2017-09-03 18:24:15

标签: java arraylist hashmap

我想我有:

  • 一个Hashmap_A,由object_A组成(然后例如为了在HashMap中推送一个新对象,我使用'myHashmap_A.put(KEY_integer,myObject_A)'); object_A是类A的istance,具有属性Attribute_A1和Attribute_A2。
  • 由object_B组成的Hashmap_B; object_B是B类的istance,具有属性Attribute_B1和Attribute_B2。
  • 由object_C组成的Hashmap_C; object_C是C类的istance,具有属性Attribute_C1和Attribute_C2。
  • 等...

我希望有一个泛型方法来构建object_xxx的ArrayList,其中Attribute_xxx = K,然后用于任何HashMap。

类似于:myHashmap_xxx.getArrayList(nameOfAttribute_xxx,K);

有什么想法吗?

新编辑:

根据'JB Nizet'的回答,我应该有:

import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Collector;

public static <O> List<O> getObjectWithAttributeEqualTo(Map<?, O> MyMap_Arg, Function<O, ?> MY_AttributeValueExtractor_Arg, Object MY_AttributeValueToEqual_Arg) {
        return MyMap_Arg.stream().filter(o -> MY_AttributeValueExtractor_Arg.apply(o).equals(MY_AttributeValueToEqual_Arg)).collect(Collectors.toList());
}

它对我不起作用,因为我的IDE(Netbeans)找不到方法流();看看文档,stream()似乎是List的一个方法,而不是Map ...

我试图以这种方式修改它(添加'values()'),它最终不会在IDE中给我任何错误:

public <O> List<O> getObjectWithAttributeEqualTo(Map<?, O> MyMap_Arg, Function<O, ?> MY_AttributeValueExtractor_Arg, Object MY_AttributeValueToEqual_Arg) {
    return  MyMap_Arg.values().stream().filter(o -> MY_AttributeValueExtractor_Arg.apply(o).equals(MY_AttributeValueToEqual_Arg)).collect(Collectors.toList());
}

现在问题是另一个问题;假设我有一个名为'CAR'的类,其中包含NOT STATIC方法'getColor()'。我有对象'myHashMap',这是carr的地图,然后是HashMap。我想要例如获取myHashMap中的红色汽车列表。如果我使用:

List<Car> redCars = getValuesWithAttributeEqualTo(myHashMap, Car::getColor, "red");

我在IDE中遇到错误,因为它说getColor不是静态的(并且它不能是静态的,我不能更改它)。

如果我使用答案中建议的其他方法:

List<Car> redCars = getValuesWithAttributeEqualTo(myHashMap, car -> car.getColor(), "red");

我不明白什么是汽车;它是汽车的一个例子吗?如果我把'新车()'而不是车,它不起作用......

1 个答案:

答案 0 :(得分:1)

您无法在Java中按名称获取属性。或者更确切地说,你可以,但它需要使用反射,这几乎总是一个坏主意:它使代码不是类型安全,慢,不可重构。

因此,您应该做的是传递一个允许获取属性值的函数,而不是使用属性 name

假设您有Map<Integer, Car>(请注意接口的使用,而不是具体类型。请注意泛型类型的使用。请注意Java命名约定的尊重,使代码可读)。

假设汽车有一个属性&#34;颜色&#34; (因此,方法getColor()返回,例如,字符串)。并且假设您想要将所有颜色等于&#34;红色&#34;的汽车提取到列表中,方法体看起来像这样:

List<Car> result = map.values().stream().filter(o -> o.getColor().equals("red")).collect(Collect‌​or.to‌​List());

这一行很简单,我认为你不需要提取一个通用方法来与其他类型的对象一起使用。如果您必须使用Map<Integer, Animal>和属性species执行相同操作,则只需再次键入以上内容:

List<Animal> result = map.values().stream().filter(o -> o.getSpecies().equals("dog")).collect(Collect‌​or.to‌​List());

如果您真的想要将这一简单的代码行提取到泛型方法,您需要:

  • 对象类型的通用类型(前面示例中的Car或Animal)
  • 该函数的类型,允许从对象获取属性值:这将是一个函数:

public <O> List<O> getValuesWithAttributeEqualTo(Map<?, O> map, Function<O, ?> attributeValueExtractor, Object valueToEqual) {
    // ...
}

其实施将是

public <O> List<O> getValuesWithAttributeEqualTo(Map<?, O> map, Function<O, ?> attributeValueExtractor, Object valueToEqual) {
    return map.stream().filter(o -> attributeValueExtractor.apply(o).equals(valueToEqual)).collect(Collectors.toList());
}

你会这样称呼它:

Map<Integer, Car> map = ...:
List<Car> redCars = getValuesWithAttributeEqualTo(map, car -> car.getColor(), "red");

或使用方法参考:

Map<Integer, Car> map = ...:
List<Car> redCars = getValuesWithAttributeEqualTo(map, Car::getColor, "red");

但是再一次,这种方法的内联版本非常简单易读,理解和适应,我首先不会创建这个getValuesWithAttributeEqualTo