LeetCode 3Sum Java Solution I have this Java solution to LeetCode's 3Sum problem.
I would be really grateful if I could get feedback on correctness, scalability, efficiency, coding best practices, and OOP design.
I'm relatively new to Java.
class Solution
{
    public List&lt;List&lt;Integer&gt;&gt; threeSum(int[] nums)
    {
        List l1 = new ArrayList&lt;ArrayList&gt;();
        
        for (int idx = 0; idx &lt; nums.length; idx++)
        {
            if (idx &gt; 0 &amp;&amp; nums[idx] == nums[idx - 1]) continue;

            HashMap&lt;Integer, Integer&gt; hash = new HashMap&lt;&gt;();
            
            for (int idxInner = idx + 1; idxInner &lt; nums.length; idxInner++)
            {
                if (
                     hash.get(nums[idxInner]) != null &amp;&amp; 
                     nums[idxInner]+hash.get(nums[idxInner]) == -1*nums[idx]
                   )
                {
                    List l2 = new ArrayList&lt;Integer&gt;();
                    
                    addInList(l2, nums[idx]);
                    addInList(l2, hash.get(nums[idxInner]));
                    addInList(l2, nums[idxInner]);

                    l1.add(l2);
                }
                else
                {
                    hash.put(-1*(nums[idx] + nums[idxInner]), nums[idxInner]);
                }
            }
        }
        
        removeDuplicates(l1);
        
        return l1;
    }
    
    public void addInList(List&lt;Integer&gt; list, int num)
    {
        if (list == null) return;
        
        int lSize = list.size();
        
        if (lSize == 0)
        {
            list.add(num);
            return;
        }
        
        int idx = 0;
        while (idx &lt; lSize &amp;&amp; list.get(idx) &lt; num)
        {
            idx++;
        }
        
        if (idx &lt; lSize) list.add(idx, num);
        else list.add(num);
        
        return;
    }
    
    public void removeDuplicates(List&lt;ArrayList&lt;Integer&gt;&gt; lists)
    {
        if(lists == null) return;

        for(int outer = 0; outer &lt; lists.size(); outer++)
        {
            for(int inner = outer + 1; inner &lt; lists.size(); inner++)
            {
                
                if (areDuplicates(lists.get(outer), lists.get(inner)))
                {
                    
                    lists.remove(inner);
                    inner--;
                }
            }
        }
    }
                    
    public boolean areDuplicates(ArrayList&lt;Integer&gt; first, ArrayList&lt;Integer&gt; second)
    {
        if (first == null &amp;&amp; first == second) return true;
        if (first == null || second == null) return false;
        
        int fSize = first.size();
        int sSize = second.size();
        
        if (fSize != sSize) return false;
        
        for(int idx = 0; idx &lt; fSize; idx++)
        {
            if (first.get(idx) != second.get(idx)) return false;
        }
        
        return true;        
    }
}

I get a timeout error on LeetCode if I try to run this.
This is a nice start, but there's some stylistic stuff that could be improved.
Generally it's a good idea to name variables for what their purpose is. Names like l1 are difficult to understand. This varies depending on the language, but in Java people tend to be explicit with their variable naming, preferring descriptive names over concise ones.
When declaring a data structure, convention in Java is to declare the type as the interface.
public boolean areDuplicates(ArrayList&lt;Integer&gt; first, ArrayList&lt;Integer&gt; second)

is more commonly written as
public boolean areDuplicates(List&lt;Integer&gt; first, List&lt;Integer&gt; second)

This is because List defines a set of behaviours that you want to have, and ArrayList defines how they are implemented. If someone has made a data structure with the exact same behaviour as an ArrayList, then you want your methods to support that data structure as well.
The format of the code in quite unusual for Java. I'd run your code through an autoformatter, which deals with all that stuff for you. Personally I use Eclipse's default one, but there's loads of choice out there.
This isn't a complete review, and it's mainly my opinion, so feel free to include or discard this advice.