Adarsh Srivastava
Adarsh Srivastava

Reputation: 476

Wrong Answer using `get` method of ArrayList

While solving this question, I am getting wrong answer on some of the test cases of the problem using the get method of ArrayList directly in condition check.

Code failing the test cases:

import java.io.*;
import java.util.*;
import java.text.*;
import java.math.*;
import java.util.regex.*;

public class Solution {
    public static void main(String[] args) {
        Scanner sc=new Scanner(System.in);
        int n=sc.nextInt();
        Stack <Integer> s= new Stack<>();
        ArrayList <Integer> m= new ArrayList<>();
        
        for(int i=0;i<n;i++){
            int x=sc.nextInt();
            if(x==1){
             int y=sc.nextInt();
             if(m.isEmpty() || y>=m.get(m.size()-1))
                 m.add(y);
             s.push(y);  
             
            }
            else if(x==2){
               // Here I am using `get` to check the last value of ArrayList with the top of stack
               if(m.get(m.size()-1)==s.peek()) {
                   m.remove(m.size()-1);
               }
               s.pop();
            }
            else {
                System.out.println(m.get(m.size()-1));
            }
        }
    }
}

But when assigned the same syntax to a variable and used that for the condition check it passed.

Code passing all the test cases:

import java.io.*;
import java.util.*;
import java.text.*;
import java.math.*;
import java.util.regex.*;

public class Solution {
    public static void main(String[] args) {
        Scanner sc=new Scanner(System.in);
        int n=sc.nextInt();
        Stack <Integer> s= new Stack<>();
        ArrayList <Integer> m= new ArrayList<>();
        
        for(int i=0;i<n;i++){
            int x=sc.nextInt();
            if(x==1){
             int y=sc.nextInt();
             if(m.isEmpty() || y>=m.get(m.size()-1))
                 m.add(y);
             s.push(y);  
             
            }
            else if(x==2){
                // When assigning the same to a variable it passed all test cases.
                int a = m.get(m.size()-1); 
               if(a==s.peek()) {
                   m.remove(m.size()-1);
               }
               s.pop();
            }
            else {
                System.out.println(m.get(m.size()-1));
            }              
        }
    }
}

As I am new to Java, I am confused with the use of the get method of the ArrayList. Please explain to me about the inner working of the get method that why it is failing or am I missing something?

Upvotes: 0

Views: 250

Answers (3)

user2862981
user2862981

Reputation: 294

I think that the problem is related to automatic boxing/unboxing of Integer type. In the statement

 if(a==s.peek())

the comparison is done comparing the an integer value (a) to the unboxed Integer (s.peek()).

In the statement

 m.get(m.size()-1)==s.peek()

the comparison is done comparing between two Integer values, that is between two references. Since the two references are different the equality check fails.

To fix the latest statement you can use:

 m.get(m.size()-1).intValue()==s.peek().intValue()
 

Or use the equals method of Integer type.

Upvotes: 1

Thomas Kl&#228;ger
Thomas Kl&#228;ger

Reputation: 21435

s and m store Integer objects and you should never compare objects using ==.

Replace m.get(m.size()-1)==s.peek() with m.get(m.size()-1).equals(s.peek()) and your code will work.

The reason that your second approach works is that by assigning m.get(m.size()-1) to an int variable the Integer value is unboxed, and then the comparison a==s.peek() is done on the int values (the value from s.peek() is unboxed too).

Upvotes: 1

Amongalen
Amongalen

Reputation: 3131

I didn't look at the task itself (as a question should be self-contained and I'm not going to visit random links) but I believe the problem comes from types you use here.

In the first case, m.get(m.size()-1)==s.peek() both right side and left side are Integers. Because of that, when you use a == sign, you are actually comparing object references. Such comparison will work only sometimes (I believe its for Integers in range from -128 to 127). You could use equals to fix the issue.

On the other hand we have int a = m.get(m.size()-1); if(a==s.peek()). Here, in the first part you're getting Integer first but then it is assigned to an int variable - unboxing happens here. Then, when you have a condition, you compare an int and an Integer. In such comparison, the Integer gets unboxed to an int and a comparison on simple ints happen here (see first point in JLS-5.6.2). Because of that it works alright in this situation.

Upvotes: 1

Related Questions