【问题标题】:Dynamic datatype in generics java泛型java中的动态数据类型
【发布时间】:2021-07-28 14:09:47
【问题描述】:

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

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.
           });
    }

【问题讨论】:

    标签: java generics java-8 functional-programming


    【解决方案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 -&gt; f.apply(o)).collect(Collectors.toMap(result -&gt; 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 -&gt; f.apply(o)),这样就不需要在collect 中调用两次。
          猜你喜欢
          • 1970-01-01
          • 2013-08-04
          • 1970-01-01
          • 2013-05-29
          • 1970-01-01
          • 2018-10-24
          • 1970-01-01
          • 2011-02-28
          • 1970-01-01
          相关资源
          最近更新 更多