使用HashMap <string,runnable =“”>来避免重复的方法

时间:2017-07-10 09:05:13

标签: lambda java-8 hashmap

问候,我有一些定义如下的功能:

@RequestMapping(value = "/getWeek", method = RequestMethod.GET)
public ResponseEntity<?> getAvgWeek(BigInteger id) {
    List<TimePeriodCalc> result = Calc.getWeek(id);
    return new ResponseEntity<>(result, HttpStatus.OK);
}

并且

@RequestMapping(value = "/getMonth", method = RequestMethod.GET)
public ResponseEntity<?> getAvgMonth(BigInteger id) {
    List<TimePeriodCalc> result = Calc.getMonth(id);
    return new ResponseEntity<>(result, HttpStatus.OK);
}

也许getYear,getQuarter,getDate ....

现在我想将它们组合起来并添加一个参数来告诉我需要返回什么。 现在的问题是我必须定义switch case语句,这可能会使我的代码冗长且不专业。 无论如何我可以像这种情况一样使用Lambda表达式:

HashMap<String, Runnable> myMap = .... (declare and input some values)
myMap.put("executeA", () -> funA())
myMap.get("executeA")

然后我的代码看起来像:

result = myMap.get("week"); 
//Or any kinds of assignment, the map does not have to return a list

或:

result = myMap.get("year");

依旧......

谢谢。

1 个答案:

答案 0 :(得分:3)

假设getWeekgetMonth等方法都采用相同的单个参数(BigInteger,根据您的评论),您可以创建Map映射字符串到Function<BigInteger, List<TimePeriodCalc>>并使用静态方法引用填充此地图...

Map<String, Function<BigInteger, List<TimePeriodCalc>>> myMap = new HashMap<>();
myMap.put("week", Calc::getWeek);
myMap.put("month", Calc::getMonth)
...

...然后从地图中获取正确的函数,并在通用方法中使用apply

@RequestMapping(value = "/getAny", method = RequestMethod.GET)
public ResponseEntity<?> getAvgAny(String period, BigInteger id) {
    List<TimePeriodCalc> result = myMap.get(period).apply(id)
    return new ResponseEntity<>(result, HttpStatus.OK);
}

关于您的评论:对于具有一个参数的函数,Java仅具有Function,对于两个参数具有BiFunction,即 x - &gt; y (x,y) - &gt; ž。具有两个以上参数的AFAIK函数或方法引用是不可能的。如果必须传递两个以上的参数,则可以使用Supplier,使用 no 参数,但访问其范围内的变量。但是,这需要在方法中定义Map

@RequestMapping(value = "/getAny", method = RequestMethod.GET)
public ResponseEntity<?> getAvgAny(String period, BigInteger id, many other parameters) {    
    Map<String, Supplier<List<TimePeriodCalc>>> myMap = new HashMap<>();
    myMap.put("week",  () -> Calc.getWeek(id and many other parameters));
    ...
    List<TimePeriodCalc> result = myMap.get(period).get();
    return new ResponseEntity<>(result, HttpStatus.OK);
}

或者您可以将不同的参数包装到Object[]中并将其传递给函数:

Map<String, Function<Object[], List<TimePeriodCalc>>> myMap = new HashMap<>();
myMap.put("week",  p -> Calc.getWeek((BigInteger) p[0], (Some) p[1], (Other) p[2], (Class) p[3]));
...

@RequestMapping(value = "/getAny", method = RequestMethod.GET)
public ResponseEntity<?> getAvgAny(String period, BigInteger id, many other parameters) {    
    Object[] params = new Object[] {id and  many other parameters};
    List<TimePeriodCalc> result = myMap.get(period).apply(params);
    return new ResponseEntity<>(result, HttpStatus.OK);
}

正如by Holger in comments所指出的,您还可以定义自己的接口,提供具有两个以上参数的单个函数,然后创建Map个,使用lambda实现该方法并从中映射那些你要调用的函数的参数。

interface MyInterface {
    List<TimePeriodCalc> getResult(BigInteger id, some more stuff);
}

Map<String, MyInterface> myMap = new HashMap<>();
myMap.put("week", (id, more, stuff) -> Calc.getweek(id, more, stuff));
...
List<TimePeriodCalc> test = myMap.get("week").getResult(id, more, stuff);