Issue
How do I fix this code block (in ifPresentOrElse())?
I'm stuck here with:
Inconvertible types; cannot cast '<lambda parameter>' to 'char'
Please advise how to get this compiled and running.
public static boolean isBracketsInOrder1(String bracket) {
    
    Stack<Character> charStack = new Stack<>();
    static Map<Character, Character> leftToRightBracketsMap = 
                                       Map.of('{', '}', '[', ']', '(', ')');
    bracket.chars()
        .filter(i -> leftToRightBracketsMap.containsKey((char) i))
        .findFirst()
        .ifPresentOrElse((i) -> charStack.push((char) i),
            (i) -> {
                // code does not COMPILE at equals((char) i)
                return leftToRightBracketsMap.get(charStack.pop()).equals((char) i);
            });
    return true;
}
And this is the working code using for loop representing what I'm trying to implement above using streams above.
public static boolean isBracketsInOrder(String bracket) {
    Stack<Character> charStack = new Stack<>();
    static Map<Character, Character> leftToRightBracketsMap = 
                                       Map.of('{', '}', '[', ']', '(', ')');
    boolean matchFound = true;
    for (char c : bracket.toCharArray()) {
        if (leftToRightBracketsMap.containsKey(c)) charStack.push(c);
        else {
            char leftBrack = charStack.pop();
            char correctBrack = leftToRightBracketsMap.get(leftBrack);
            if (c != correctBrack) return false;
        }
    }
    return true;
}
Solution
You've introduced the code for a very basic algorithmic question - validate a string of brackets.
There are many mistakes in your code:
- A stream doesn't act precisely like a loop, when it hits the terminal operation (which is - findFirst()in your code), it's done. Code inside- ifPresentOrElse()would not be executed multiple times (you probably expected the opposite). It would be invoked only once on an optional result returned by the- findFirst().
- As its second argument - ifPresentOrElse()expects an instance of the- Runnableinterface. Method- run()neither expects any arguments, no returns a value. Therefore, this attempt to define a- Runnableis incorrect:- (i) -> { return something; }.
- Any lambda expressions should to conform to a particular functional interface (see). It can't appear out of nowhere. 
- Class - Stackis legacy, it's still in the JDK for backward compatibility reasons. Implementations of the- Dequeinterface should be used instead.
- You are not checking whether the stack is empty, which can cause an - EmptyStackException. If you would replace the- Stackwith- ArrayDequethe problem will remain, method- pop()will throw- NoSuchElementException. You need to make sure that stack is not empty.
- Returning - truein the imperative solution is not correct. Instead, you need to return- charStack.isEmpty(), because if there are some elements in the stack - sequence is not valid, there are brackets that haven't been closed.
Implementing this problem using streams requires far more efforts than a solution using a plain loop.
According to the documentation, the only place where mutation can occur in a stream is inside the collector. As a general rule, all functions used in a stream pipeline should not operate via side effects and accumulate the stated outside the stream (apart from some edge cases, see the link). Only collector's mutable container should maintain a state.
We can contract such a collector using Collecor.of() method:
public static boolean isValidBracketSequence(String brackets) {
    return brackets.chars()
        .mapToObj(c -> (char) c)
        .collect(getBracketCollector());
}
public static Collector<Character, ?, Boolean> getBracketCollector() {
    
    return Collector.of(
        BracketContainer::new,
        BracketContainer::add,
        (left, right) -> { throw new AssertionError("should not be executed in parallel"); },
        bracketContainer -> bracketContainer.isValid() && bracketContainer.isEmpty()
    );
}
That's how a mutable container might look like:
class BracketContainer {
    public static final Map<Character, Character> leftToRightBracketsMap =
        Map.of('(', ')', '[', ']', '{', '}');
    
    private Deque<Character> stack = new ArrayDeque<>();
    private boolean isValid = true;
    
    public void add(Character next) {
        if (!isValid) return;
        
        if (leftToRightBracketsMap.containsKey(next)) {
            stack.push(next);
        } else {
            compare(next);
        }
    }
    
    public void compare(Character next) {
        
        this.isValid = !isEmpty() && leftToRightBracketsMap.get(stack.pop()).equals(next);
    }
    
    public boolean isEmpty() {
        return stack.isEmpty();
    }
    
    public boolean isValid() {
        return isValid;
    }
}
main()
public static void main(String[] args) {
    System.out.println("(([])) -> " + isValidBracketSequence("(([]))")); // true
    System.out.println("(([]]) -> " + isValidBracketSequence("(([]])")); // false
    System.out.println("(([})) -> " + isValidBracketSequence("(([}))")); // false
    System.out.println("({[])) -> " + isValidBracketSequence("({[]))")); // false
    System.out.println("({[]}) -> " + isValidBracketSequence("({[]})")); // true
}
Output:
(([])) -> true
(([]]) -> false
(([})) -> false
({[])) -> false
({[]}) -> true
Answered By - Alexander Ivanchenko Answer Checked By - Pedro (PHPFixing Volunteer)
 
 Posts
Posts
 
 
0 Comments:
Post a Comment
Note: Only a member of this blog may post a comment.