Two quite different Java solutions.

**Solution 1: Split the splits** (10 lines, 880 ms)

Split the whole expression into terms on `+`

and `-`

. Split each term on `*`

and `/`

. Split with look-ahead, so the operators remain in the strings as the first character. Otherwise I'd lose them. Also, I don't have to deal with `+`

/`-`

myself since `parseInt`

will get the number including the `+`

/`-`

prefix and do it for me.

```
public int calculate(String s) {
int total = 0;
for (String t : s.replace(" ", "").split("(?=[+-])")) {
int term = 1;
for (String u : ('*' + t).split("(?=[*/])")) {
int n = Integer.parseInt(u.substring(1));
term = u.startsWith("*") ? term * n : term / n;
}
total += term;
}
return total;
}
```

**Solution 2: One pass through the tokens** (16 lines, 436 ms)

Turn the input into tokens (operators and numbers) and process them front to back. Keep track of the total as well as the current term.

```
public int calculate(String s) {
StringTokenizer tokens = new StringTokenizer('+' + s.replace(" ", "") + "+0", "+-*/", true);
long total = 0, term = 0;
while (tokens.hasMoreTokens()) {
String op = tokens.nextToken();
if ("+-".contains(op)) {
total += term;
term = (op.equals("+") ? 1 : -1) * Long.parseLong(tokens.nextToken());
} else {
long n = Long.parseLong(tokens.nextToken());
if (op.equals("*"))
term *= n;
else
term /= n;
}
}
return (int)total;
}
```

Instead of `(op.equals("+") ? 1 : -1)`

you could also do `" +".indexOf(op)`

, but it's trickier and slower. Or `(44 - op.charAt(0))`

, which is even trickier.