Reputation: 463
Greeting, I have some functions defined like :
@RequestMapping(value = "/getWeek", method = RequestMethod.GET)
public ResponseEntity<?> getAvgWeek(BigInteger id) {
List<TimePeriodCalc> result = Calc.getWeek(id);
return new ResponseEntity<>(result, HttpStatus.OK);
}
And
@RequestMapping(value = "/getMonth", method = RequestMethod.GET)
public ResponseEntity<?> getAvgMonth(BigInteger id) {
List<TimePeriodCalc> result = Calc.getMonth(id);
return new ResponseEntity<>(result, HttpStatus.OK);
}
And maybe getYear, getQuarter, getDate ....
Now I would like to combine them and add one parameter to tell me what I need to return. The problem now is I have to define switch case statement which may make my code lengthy and unprofessional. Is there anyway I can use Lambda expression like this case :
HashMap<String, Runnable> myMap = .... (declare and input some values)
myMap.put("executeA", () -> funA())
myMap.get("executeA")
Then my code would look like :
result = myMap.get("week");
//Or any kinds of assignment, the map does not have to return a list
or :
result = myMap.get("year");
and so on ...
Thank you.
Upvotes: 2
Views: 829
Reputation: 82899
Assuming that the getWeek
, getMonth
etc. methods all take the same single parameter (a BigInteger
, according to your comment) you can create a Map
mapping strings to Function<BigInteger, List<TimePeriodCalc>>
and populate this map with static method references...
Map<String, Function<BigInteger, List<TimePeriodCalc>>> myMap = new HashMap<>();
myMap.put("week", Calc::getWeek);
myMap.put("month", Calc::getMonth)
...
... and then get the proper function from the map and apply
it in your generic method:
@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);
}
Concerning your comment: Java only has Function
for functions with one parameter, and BiFunction
for two parameters, i.e. x -> y and (x, y) -> z. AFAIK functions or method references with more than two parameters are not possible. If you have to pass more than two parameters, you could, as a workaround, use a Supplier
, taking no parameters but accessing the variables in its scope. This, however, would require the Map
to be defined within the method:
@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);
}
Or you might wrap the different parameters into an Object[]
and pass that to the function:
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);
}
As pointed out by Holger in comments, you can also define your own interface providing a single function with more than two parameters and then create a Map
of those, using a lambda to implement that method and mapping from those parameters to the function you want to call.
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);
Upvotes: 3