1

I have read this post How to use if-else logic in Java 8 stream forEach

The whole point of Java 8 is to write more elegant, readable and concise code. I rewrote this execute method utilizing Java 8 Streams and Lambda but what i end up with doesn't look any different from the Java 7 version.

private static boolean execute(String expression) {
    Deque<Character> stack = new ArrayDeque<>();
    for (char c : expression.toCharArray()) {
        if (isOpenToken(c)) {
            stack.push(c);
        } else if (stack.isEmpty() || !matches(stack.pop(), c)) {
            return false;
        }
    }
    return stack.isEmpty();
}

This is what the method looks like now in Java 8

private static boolean execute(String expression) {
    char[] a = expression.toCharArray();
    Deque<Character> stack = new ArrayDeque<>();
    IntStream.range(0, a.length).forEach(i -> {
        if (isOpenToken(a[i])) {
            stack.push(a[i]);
        } else {
            matches(stack.pop(), a[i]);
        }
    });
    return stack.isEmpty();
}

Is there a more elegant way of doing this in Java 8?

8
  • 8
    It is a common misconception that everything will "become more elegant" when you use streams. This code right now is perfectly fine, you should not replace every for loop in your code to use streams. Commented Mar 9, 2019 at 10:30
  • You might be interested in chars() method from String. Commented Mar 9, 2019 at 10:32
  • You should as well note that your stream version and your initial Java 7 solution won’t do the same. In the first version you have an early exit if !matches(stack.pop(), c). This is gone in the stream version. Commented Mar 9, 2019 at 20:54
  • @dpr Yes both versions produce the same result but go about it differently. I reckon though that the Java 8 would be slower because it has to go through all items in the list. This is because you can't have break or return using forEach. However, in the end stack.isEmpty() can either be true or false. I have decided to use the Java 7 version. Commented Mar 10, 2019 at 0:23
  • Upvote for not converting to streams. Commented Mar 10, 2019 at 7:30

1 Answer 1

1

Not much, that can be done here, streams are great for mapping, filtering, aggregating, collecting... Here you only have side effects for every element. You might wanna use some of functional goodness of streams by applying mapping:

IntStream.range(0, a.length).map(i -> a[i]).forEach(el -> {
    if (isOpenToken(el)) {
        stack.push(el);
    } else {
        matches(stack.pop(), el);
    }
});
Sign up to request clarification or add additional context in comments.

1 Comment

It would make more sense to use expression.chars() to get an IntStream over the chars without copying everything into an array first.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.