【问题标题】:Normalize the lambda operation across different objects标准化跨不同对象的 lambda 操作
【发布时间】:2019-12-26 19:40:18
【问题描述】:

在下面的代码中,您可以看到针对具有不同对象的多个映射发生的常见 lambda 操作。我想知道是否可以在调用时定义一个执行相同操作的通用函数。

Map<Int, Object1> map1.entrySet()
                      .stream()
                      .collect(Collectors.toMap(Map.Entry::getKey, e -> e.getValue().getDisplayName()))

Map<Int, Object2> map2.entrySet()
                      .stream()
                      .collect(Collectors.toMap(Map.Entry::getKey, e -> e.getValue().getDisplayName()))

Map<Int, Object3> map2.entrySet()
                      .stream()
                      .collect(Collectors.toMap(Map.Entry::getKey, e -> e.getValue().getDisplayName()))

在上面,object1、object2和object3属于不同的类型(类)。

假设所有对象 obj1、obj2、obj3 都具有共同的属性 displayName。

【问题讨论】:

  • Object1/2/3 是否共享任何界面?如果不是,他们getValue()的类型是一样的吗?
  • 两者都没有。那就是问题所在。如果 getValue() 相同,这是否意味着对象属于同一类?我想要一个接受具有不同类对象的映射并执行上述操作的方法。
  • 我误解并认为getValueObject1 上的方法,而不是Entry 上的方法。

标签: function lambda functional-programming


【解决方案1】:

没有反射你能做的最好的事情是传递一个 lambda 来获取属性:

public <K, T1, T2> Map<K, T2> mapValues(Map<K, T1> source, Function<T1, T2> function) {
    return source.entrySet()
                 .stream()
                 .collect(Collectors.toMap(Map.Entry::getKey, e -> function.apply(e.getValue())));
}

// use
mapValues(map1, Object1::getDisplayName)
mapValues(map2, Object2::getDisplayName)

(Kotlin 在标准库中有这个方法的等价物)

有了反射,你可以做到

public <K, T> Map<K, String> mapDisplayName(Map<K, T> source, Class<T> clazz) {
    Method m = clazz.getMethod("getDisplayName");
    return source.entrySet()
                 .stream()
                 .collect(Collectors.toMap(Map.Entry::getKey, e -> (String) m.invoke(e.getValue())));
}

// use
mapValues(map1, Object1.class)
mapValues(map2, Object2.class)

但它不太安全,也不太有用,以换取……不是那么方便。

【讨论】:

    猜你喜欢
    • 2021-01-31
    • 2012-09-25
    • 2022-08-22
    • 1970-01-01
    • 2018-08-09
    • 2018-12-19
    • 2022-12-05
    • 1970-01-01
    • 2021-09-16
    相关资源
    最近更新 更多