假设我有:
- 一个 Hashmap_A,由 object_A 组成(例如,为了将新对象推送到 HashMap 中,我使用 'myHashmap_A.put( KEY_integer, myObject_A)' ); object_A 是 A 类的实例,具有属性 Attribute_A1 和 Attribute_A2。
- 一个 Hashmap_B,由 object_B 组成; object_B 是 B 类的实例,具有属性 Attribute_B1 和 Attribute_B2。
- 一个 Hashmap_C,由 object_C 组成; object_C 是类 C 的实例,具有属性 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();查看文档,stream() 似乎是列表的方法,而不是映射的方法......
我尝试用这种方式修改它(添加'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”的类,具有非静态方法“getColor()”。我有对象“myHashMap”,它是 carr 的映射,然后是 HashMap。例如,我想要获取 myHashMap 中的红色汽车列表。如果我使用:
List<Car> redCars = getValuesWithAttributeEqualTo(myHashMap, Car::getColor, "red");
我在 IDE 中收到错误,因为它表示 getColor 不是静态的(而且它一定不是静态的,我无法更改它)。
如果我使用答案中建议的其他方法:
List<Car> redCars = getValuesWithAttributeEqualTo(myHashMap, car -> car.getColor(), "red");
我不明白什么是汽车;它是 Car 的一个实例吗?如果我用“new Car()”代替 car,它就不起作用...
最佳答案
在 Java 中无法通过名称获取属性。或者更确切地说,你可以,但它需要使用反射,这几乎总是一个坏主意:它使代码不类型安全,速度较慢,不可重构。
因此,您应该传递一个允许获取属性值的函数,而不是使用属性名称。
假设您有 Map<Integer, Car>
(注意接口(interface)的使用,而不是具体类型。并注意泛型类型的使用。并注意尊重 Java 命名约定,使代码可读)。
假设 Car 有一个属性“color”(因此方法 getColor()
返回一个字符串)。假设您想将颜色等于“红色”的所有汽车提取到列表中,方法主体将如下所示:
List<Car> result = map.values().stream().filter(o -> o.getColor().equals("red")).collect(Collector.toList());
这一行非常简单,我认为您不需要提取通用方法来对其他类型的对象执行此操作。如果您必须对 Map<Integer, Animal>
做同样的事情和属性(property)species
,您只需再次输入上面的内容:
List<Animal> result = map.values().stream().filter(o -> o.getSpecies().equals("dog")).collect(Collector.toList());
如果您确实想将这行简单的代码提取到通用方法中,您需要:
- 对象类型的通用类型(前面示例中的 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
首先。
关于java - 如何从具有通用条件的通用 HashMap 中获取 ArrayList,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46026556/