CategoriesJavaKotlinSoftware Development

What’s Wrong With Stack in Java and Kotlin?

This is a story about me accidentally crossing paths with the Stack API in Java and Kotlin. Whether you are a seasoned Java and/or Kotlin developer or are just beginning to test the waters. I promise you that by the end of this blog I will convince you to never touch the Stack class in Java/Kotlin even with a ten-foot poll.

Before we dive right in, let’s brush up our memory real quick so that we can enjoy the rest of the show.

What is a Stack?

In computer science, a Stack refers to a data structure for maintaining a collection of elements and it majorly supports these two operations:

  1. push, which allows you to add an element to the collection, and
  2. pop, which allows you to remove an element from the top of the collection.

Based on this information, we can say that it follows a LIFO (last in first out) strategy.

Next, let’s look at some common applications of stacks in real life.

Where are Stacks used?

Expression Evaluation & Conversion

We use stacks to evaluate infix, postfix and prefix expressions. Further, you can also convert from one type of expression to another using a stack.

Syntax Parsing

Compilers use a stack to parse the syntax of expressions in the source code.

Backtracking

If you are solving a problem to find a path in a maze. You can use a stack to backtrack the path if you hit a wall.

Parenthesis Checking

To validate if a parenthesis is opening and closing correctly, a Stack is pretty handy.

Now there are many more creative applications of stacks in real life but for the scope of this blog these should suffice.

Time to dive into some code.

Reverse a String

Now to keep the example simple to follow, let’s say we want to reverse a string.

Imagine we get “hello world” as the input. Our method should return “dlrow olleh“.

Here goes the code to do that

public class Main {
    public static void main(String[] args) {
        System.out.println(reverse("hello world"));
    }
    
    public static String reverse(String input) {
        Stack<Character> stack = new Stack();
        
        for (char c : input.toCharArray()) {
            stack.push(c);
        }
        
        StringBuilder sb = new StringBuilder();
        while (!stack.isEmpty()) {
            sb.append(stack.pop());
        }
        
        return sb.toString();
    }
    
}

Running the above code, should give you the following output

dlrow olleh

So far so good? 😎 From here on, things will only go south.

Randomly Accessing a Stack

What do you think will happen if you were to do this?

public class Main {
    public static void main(String[] args) {
    
        String input = "hello world";
        
        Stack<Character> stack = new Stack();
        
        for (char c : input.toCharArray()) {
            stack.push(c);
        }
        
        int top = stack.size() - 1;
        int bottom = 0;
        
        System.out.println("Char on top " + stack.get(top));
        System.out.println("Char at the bottom " + stack.get(bottom));
        
    }
    
}
  1. Do you think it fail to compile?
  2. Will it throw an exception at runtime?
  3. Or Do you think it will execute and output the following text:
    Char on top d
    Char at the bottom h

Now, before you try to answer the question. Let me make it clear that, I am trying to access the elements of the Stack by their position, as if it was an Array or an ArrayList in Java.

If you picked option 3, you are ✅. In Java and Kotlin, you can randomly access elements in a Stack.

Let’s make things more interesting. By trying to iterate over this stack.

Iterating Over a Stack

If you were to try to execute this piece of code, what do you think will happen?

public class Main {
    public static void main(String[] args) {
    
        String input = "hello world";
        
        Stack<Character> stack = new Stack();
        
        for (char c : input.toCharArray()) {
            stack.push(c);
        }
        
        Iterator it = stack.iterator();
        while (it.hasNext()) {
            System.out.print(it.next());    
        }

    }
    
}

Can you say which of the two following outputs, would this execution produce?

  1. hello world
  2. dlrow olleh

If you picked option 1, you are ✅. Even though your intuition would tell you otherwise, Java and Kotlin would print the elements in the FIFO (first in first out) order. 🙈

Why are Stacks Misbehaving?

Java like any other language was written by human engineers. Just like we do, they also made a bad design decision. The decision was to extend Stack class with Vector class.

This is the reason why we have random access in the Java and Kotlin Stacks and a FIFO strategy based iterator.

Also, this is not something new but a very old bug, which was actually reported back in 2001. However, it was closed with the following comment:

It was an incorrect design decision to have Stack extend Vector (“is-a” rather than “has-a”). We sympathize with the submitter but cannot fix this because of compatibility.

If you are interested in the bug ticket, here it is [JDK-4475301].

Stack is a Class and not an Interface!

Unlike most of the collections including but not limited to Lists, Maps and Queues, Stack is not an interface. This means that if you use it in your code, you are committing to the implementation itself. This can bite you at some point of time in future, should you feel a need to move away from it.

Before moving further, let’s quickly recall the problems with the Stack class in Java and Kotlin.

  • Stacks allow random access to the elements.
  • Iterator of the stack follows FIFO strategy and not LIFO strategy.
  • Stack exists as a Class and not an Interface in Java and Kotlin.

What Should You Use Instead?

Both Java and Kotlin offer an interface called Deque. It is short for “double ended queue” and is we usually pronounce it as “deck”.

It can be serve as a LIFO (last in first out) based collection, also referred to as a Stack. In fact the official java documentation recommends this interface over the legacy Stack class.

 This interface should be used in preference to the legacy Stack class.

Another consistency it brings along is that there is no random element access. The iterator also returns elements in the order from first (head) to last (tail).

So next time you encounter a problem where you want to use a Stack, remember not to use the Stack class directly but a Deque.

I was super amazed when I came across this information, especially because I have been writing Java code for over 7 years and I must confess I didn’t know this until very recently.


I am sure you and me aren’t the only ones who didn’t know this. Simply tweet this article out and tag as many people as you think may not know this and wait for their confessions 😄

For more such blogs you can follow me Twitter or connect with me on LinkedIn.

CategoriesAndroidAndroid StudioSoftware Development

Android Studio always modifying codeStyleSettings.xml – Fixed

Yesterday a colleague of mine started experiencing a weird issue with their android studio. Whenever they’d build the code, a change would be written to codeStyleSettings.xml file automatically.

The change at the first glance was clearly unrelated to something they had been working and hence they weren’t able to figure out what could be the cause of this issue.

What did the change look like?

<Objective-C-extensions>
  <option name="GENERATE_INSTANCE_VARIABLES_FOR_PROPERTIES" value="ASK" />
  <option name="RELEASE_STYLE" value="IVAR" />
  <option name="TYPE_QUALIFIERS_PLACEMENT" value="BEFORE" />
  <file>
    <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Import" />
    <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Macro" />
    <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Typedef" />
    <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Enum" />
    <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Constant" />
    <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Global" />
    <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Struct" />
    <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="FunctionPredecl" />
    <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Function" />
  </file>
  <class>
    <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Property" />
    <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Synthesize" />
    <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="InitMethod" />
    <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="StaticMethod" />
    <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="InstanceMethod" />
    <option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="DeallocMethod" />
  </class>
  <extensions>
    <pair source="cpp" header="h" />
    <pair source="c" header="h" />
  </extensions>
</Objective-C-extensions>

Clearly it wasn’t something related to our code since we aren’t doing anything with Objective-C in our android project. This made me want to check the android studio config on that machine, to see if some preferences were changed by mistake, or through an update or any other means.

Quickly searching for objective-c, I found that there were changes being written to the Inspections in the IDE. However, the dev denied making any such changes.

What do you think was the next obvious step for me? Google :]

Turns out, this was an old issue that someone asked about, on StackOverflow 3 years ago, and this, was the top rated and accepted answer that led us to the solution.

The <Objective-C-extensions> Section is added by the Android NDK Support Plugin. Which was added in 1.3 and is activated by default. 
If you have activated this plugin it adds the Section to your codeStyleSettings.xml. Otherwise it will be removed.

Answer by devtribe

Even though the dev had not activated this plugin on their own, maybe an update introduced this change and started causing this weird behaviour.

Here are the steps to fix the problem:

Step 1: Open Preferences in your Android Studio. Shortcut on Mac OS is Command + , (comma) and on Windows is Control + Alt + S
Step 2: Goto Plugins and find the Android NDK Support plugin
Step 3: Uncheck the box to deactivate this plugin, As soon as you do that, a warning dialog will appear asking you to disable Android APK Plugin, Click OK
Step 4: Once deactivated, click on Apply and restart your Android Studio!

Now you can remove the file from your git change log if it appears there, restart Android Studio and the problem would be fixed.

Warning: The solution requires you to disable two plugins which you might want to use at a later stage, so keep that in mind before you do that.