java - 如何从具有通用条件的通用 HashMap 中获取 ArrayList

标签 java arraylist hashmap

假设我有:

  • 一个 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(Collect‌​or.to‌​List());

这一行非常简单,我认为您不需要提取通用方法来对其他类型的对象执行此操作。如果您必须对 Map<Integer, Animal> 做同样的事情和属性(property)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首先。

关于java - 如何从具有通用条件的通用 HashMap 中获取 ArrayList,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46026556/

相关文章:

java - 在 Jackson 中使用 JsonParser.nextToken 时如何将值读取为 JSON

java - 将对象的 ArrayList 拆分为大小相等的 block ,例如在 Java 中为 1 MB

java - 如何从列表创建对象的二维数组?

android - 使用 HashMap 的多列列表中的 nullPointerException

java - HTTP 状态 404 -/xnat Apache Tomcat/8.0.26 (Ubuntu)

java - Play Framework 2.2.0 Java 电子邮件

java - 遍历java中的对象列表

android - 如何在不使用 textview 的情况下从 Hashmap 获取一个值到 Intent ?

javascript - 在 Javascript Hashmap 中使用坐标作为键的最快方法

java - 字符串到 LocalDate