Here's a working solution in Java. Obviously, there are some things that were unclear (for example, I don't know what your handleXXXXOp methods do), so liberties were taken. Otherwise, this works just fine in Java 17.
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Objects;
public class SOQ_20220605_2
{
private sealed interface Value
{
public static List<Value> asList(Object... uncheckedValues)
{
Objects.requireNonNull(uncheckedValues);
final List<Value> values = new ArrayList<>();
for (var each : uncheckedValues)
{
values.add(
switch(each)
{
case null -> throw new NullPointerException("No nulls allowed");
case Integer i -> new Argument(i);
case String s -> Operation.valueOf(s.toUpperCase());
case Argument a -> a;
case Operation o -> o;
default -> throw new IllegalArgumentException("Unexpected type! each = " + each);
}
);
}
return values;
}
}
private enum Operation implements Value
{
SOME_OP,
ANOTHER_OP,
DIFFERENT_OP,
RANDOM_OP,
;
}
private record Argument(int num) implements Value {}
public static void main(String[] args)
{
final List<Value> opsAndArgs =
Value.asList
(
"SOME_OP",
42,
"ANOTHER_OP",
99,
3,
"DIFFERENT_OP",
"RANDOM_OP",
14
);
final int result = calculateResult(opsAndArgs);
System.out.println(result);
}
private static int calculateResult(List<Value> opsAndArgs)
{
int i = 0;
while (i < opsAndArgs.size())
{
if (opsAndArgs.get(i) instanceof Operation operation)
{
i =
switch (operation)
{
case SOME_OP ->
{
handleSomeOp(
opsAndArgs.get(i + 1)
);
yield i + 2;
}
case ANOTHER_OP ->
{
handleAnotherOp(
opsAndArgs.get(i + 1),
opsAndArgs.get(i + 2)
);
yield i + 3;
}
case DIFFERENT_OP ->
{
handleDifferentOp();
yield i + 1;
}
case RANDOM_OP ->
{
yield i + 4;
//throw new UnsupportedOperationException("This has not been implemented yet.");
}
};
}
}
return i;
}
private static void handleSomeOp(Value value)
{
//do something
}
private static void handleAnotherOp(Value value1, Value value2)
{
//do something
}
private static void handleDifferentOp()
{
//do something
}
}
We create a common interface called Value, so that we can have a domain of acceptable values for our List<Value>. Then, we make it sealed, so that only the types we allow can be considered a Value. Those 2 types are Argument and Operation. We also have a method asList that handles taking in the array that you described in your question. Now, you can pass in your operations and arguments as parameters. If you wanted to pass in SOME_OP, you can either pass it in as Operation.SOME_OP or as a String via "SOME_OP". The method can handle both ways currently, but I am choosing to pass in each operation as a String. Same for the arguments. If you wanted to pass in 42, you could either pass it in as new Argument(42), or you could pass it in naked as an int via 42. The method can handle both ways currently, but I am choosing to pass in each argument as an int.
Operation is an enum that holds all of the operations you defined. If you want to add more operations, simply add them to this enum, compile, then update any of the switch statements that now fail compilation.
Argument is a record that holds arguments. Having it be an explicit type helps us separate the arguments from the operations when they are together.
The main method gathers up the values in basically the same way you did, then calls the method calculateResult, with our List<Value> values as the parameter.
calculateResult is basically the switch statement and while loop that you had in your original question. This is where most of the liberties were taken. And your switch case didn't specify what happens when it comes across an argument, so I built my solution to silently ignore arguments in the switch statement.
enumis essentially a set of named integer constant(s). So you could use integer constants in Java to get the same effect (and very similar code). Or you could create anenumthat can be converted to and from integersHashMap<String, Integer> opsAndArgs= new HashMap<String, Integer>() {{ put("SOME_OP", 0); put("ANOTHER_OP", 1); put("DIFFERENT_OP", 2); put("RANDOM_OP", 3);}};. Then you canopsAndArgs["RANDOM_OP"]to get your value back. Alternatively you can hardcode the each constant similar tofinal static int RANDOM_OP = 3;in the class you are using them, or another Operations class.