泛型java中的动态数据类型
Posted
技术标签:
【中文标题】泛型java中的动态数据类型【英文标题】:Dynamic datatype in generics java 【发布时间】:2021-07-28 14:09:47 【问题描述】:我有一个用例,客户端发送列表
Function<String, Integer> firstFn = x -> x.length();
Function<String, String> secondFn = x -> x.substring(0);
client.runTheseFunctions(Arrays.asList(firstFn, secondFn));
在代码中的runtTheseFunctions
内部,任务是执行这些函数并将其保存在一个TypedSafeMap中,其中key是函数结果类型的数据类型,value是functions.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.
);
【问题讨论】:
【参考方案1】:增强@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)
。
【讨论】:
【参考方案2】:如果函数列表包含两个或多个具有相同输出类型的函数(例如:String getFirstName、String getLastName、toMap 将失败。所以另一种选择是:
var map = list.stream().collect(groupingBy(
f -> f.apply(e).getClass(),
mapping(f -> f.apply(e), toList())
));
【讨论】:
【参考方案3】:这是您想要实现的目标的示例,您可以将其用于测试。我假设 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
【讨论】:
【参考方案4】:您可以实现您的“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);
【讨论】:
不错。我们有同样的想法伙伴;) 您可以将x.apply(o)
方法移动到map
而不是forEach
然后collect
结果。 .map(f -> f.apply(o)).collect(Collectors.toMap(result -> result.getClass(), Function.identity()));
【参考方案5】:
public static void runTheseFunctions(List<Function<Employee, ?>> lst, Employee o)
lst.stream().collect(Collectors.toMap(f -> f.apply(o).getClass(), f -> f.apply(o)));
【讨论】:
这是一个不错的解决方案。 您可以将f.apply(o)
移动到stream.map(f -> f.apply(o))
,这样就不需要在collect
中调用两次。以上是关于泛型java中的动态数据类型的主要内容,如果未能解决你的问题,请参考以下文章