Reputation: 645
I am have a general question about mapping things in java. I am not quite stuck, but I feel that my approach is not really beautiful and could cause problems if one would imagine my small private project will become bigger.
Imagine I have an array = {1, 2, 3, 4}, it does not have to be numbers, just any sign in general. Then I get an input from a user, which can only be part of an array (no invalid inputs possible). Now depends on which element they choose, a specific function will be executed. The only thing I came up with is:
switch (input) {
case array[0]:
doOneThing();
break;
case array[1]:
doAnotherThing();
break;
case array[2]:
doAThirdThing();
break;
case array[3]:
doSomethingElse();
break;
}
This method works, but is not beautiful to expand. I take every possible idea with great thanks.
Upvotes: 1
Views: 88
Reputation: 40062
You must have constants in your switch statement so what you specified won't work. You could do something like this though as an example. You're not limited to using Runnable
lambdas. Any functional Interface could be used and the appropriate arguments supplied when called.
Note that it is not a good idea to allow any
method of any
class to be invoked as it could lead to unexpected results or security issues depending on how it is to be used.
public class ThisClass {
public static void main(String[] args) {
Map<String, Runnable> map = new HashMap<>();
ThisClass tc = new ThisClass();
map.put("A", () -> tc.doOneThing());
map.put("B", () -> tc.doAnotherThing());
map.put("C", () -> tc.doAthirdThing());
map.put("D", () -> tc.doSomethingElse());
for (String str : new String[] { "A", "B", "Q", "C", "D", "E" }) {
map.getOrDefault(str, () -> tc.defaultMethod()).run();
}
}
public void doOneThing() {
System.out.println("Doing one thing");
}
public void defaultMethod() {
System.out.println("Executing default");
}
public void doAnotherThing() {
System.out.println("Doing Another thing");
}
public void doAthirdThing() {
System.out.println("Doing a third thing");
}
public void doSomethingElse() {
System.out.println("Doing something Else");
}
}
Prints
Doing one thing
Doing Another thing
Executing default
Doing a third thing
Doing something Else
Executing default
You can also do something like this.
Map<String, DoubleBinaryOperator> map = new HashMap<>();
map.put("+", (a, b) -> a + b);
map.put("-", (a, b) -> a - b);
map.put("*", (a, b) -> a * b);
map.put("/", (a, b) -> a / b);
DoubleBinaryOperator error = (a, b) -> {
throw new IllegalArgumentException();
};
for (String str : new String[] { "+", "-", "L", "/", "*" }) {
try {
double result = map.getOrDefault(str, error)
.applyAsDouble(2.0, 3.0);
System.out.println("result = " + result);
} catch (IllegalArgumentException iae) {
System.out.println("unknown operator \"" + str + "\"");
}
}
Prints
result = 5.0
result = -1.0
unknown operator "L"
result = 0.6666666666666666
result = 6.0
Upvotes: 1
Reputation: 899
Sounds like you want to look at Java Reflection Api.
Class c=Class.forName("xxxx")
where {xxxx} is a string you have constructed from parameters.
you can similarly invoke method names.
Note - beautiful code often comes at some cost - be it readability, performance or security (esp in the case of reflection). Personally i don't mind a long switch statement - it might not be pretty but it will never bite you.
Upvotes: 0
Reputation: 1550
One possible way is if you can create a name of a function using their inputted value. For example, if they input 1, you will call "function1" or if you input 2, you call "function2". Then you can use reflection to call the method by it's string name.
Something like this.
Upvotes: 0