泛型java中的动态数据类型



我有一个用例,其中客户端正在发送一个List<函数>。任务是迭代并执行此函数,并将其保存在TypedSafeMap中。伪客户端代码:

Function<String, Integer> firstFn = x -> x.length();
Function<String, String> secondFn = x -> x.substring(0);
client.runTheseFunctions(Arrays.asList(firstFn, secondFn));

在代码中的runtTheseFunctions中,任务是执行这些函数并将其保存在TypedSafeMap中,其中键是函数结果类型的数据类型,值是函数的返回值.apply((;

下方的代码

public static void runTheseFunctions(List<Function<Employee, ?>> lst, Employee o) {
lst.stream().forEach( x -> {
typedSafeMap.put(????, x.apply(o));  
//The key is nothing but the datatype of the x.apply(o).
//How do I add this in runtime here. Generics is all compile time safety.
});
}
public static void runTheseFunctions(List<Function<Employee, ?>> lst, Employee o) {
lst.stream().collect(Collectors.toMap(f -> f.apply(o).getClass(), f -> f.apply(o)));
}

您可以实现您的"runTheseFunctions;方法如下:

public static void runTheseFunctions(List<Function<Employee, ?>> lst, Employee o) {
Map<Class<?>, Object> typedSafeMap = new HashMap<>();
lst.stream().forEach(x -> {
Object value = x.apply(o);
typedSafeMap.put(value.getClass(), value);
});
System.out.println(typedSafeMap);
}

如果函数列表包含两个或多个具有相同输出类型的函数(例如:String getFirstName、String getLastName、toMap(,则会失败。因此,另一种选择是:

var map = list.stream().collect(groupingBy(
f -> f.apply(e).getClass(), 
mapping(f -> f.apply(e), toList())
));

以下是您想要实现的目标的示例,您可以将其用于测试。我假设了Employee类的一个微不足道的实现,只是为了给您一个想法:

import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
class Employee {
String name;
public Employee(String name) {
this.name = name;
}
public int length() {
return name.length();
}
public String substring(int index) {
return name.substring(index);
}
}
public class Test {
public static void main(String[] args) {
Employee e = new Employee("Marco");
Function<Employee, Integer> firstFn = x -> x.length();
Function<Employee, String> secondFn = x -> x.substring(0);
runTheseFunctions(Arrays.asList(firstFn, secondFn), e);
}
public static void runTheseFunctions(List<Function<Employee, ?>> lst, Employee o) {
Map<Class, Object> typedSafeMap = new HashMap<>();
lst.stream().forEach(x -> {
Object result = x.apply(o);
typedSafeMap.put(x.apply(o).getClass(), x.apply(o));
// The key is nothing but the datatype of the x.apply(o).
// How do I add this in runtime here. Generics is all compile time safety.
});
typedSafeMap.entrySet().forEach(entry -> System.out.println(entry.getKey() + " - " + entry.getValue()));
}
}

这是输出:

class java.lang.String - Marco
class java.lang.Integer - 5

增强@Yonas答案:

private static Map<?, ? extends Object> runTheseFunctions(List<Function<String, ? extends Object>> list, String o) {
return list.stream()
.map(f -> f.apply(o))
.collect(Collectors.toMap(result -> result.getClass(), Function.identity()));
}

这将只调用f.apply(o)一次。

最新更新