ruvinbsu
ruvinbsu

Reputation: 115

What is the difference between direct initialization of class member vs doing it within a method?

I have done a Google Foobar task and was curious about why 2 implementations, which seems to be equivalent, work in a different way. The first one brings me "Test 2 failed", when the second solution passes all test cases. I know that both of them don't follow the best OOP practices, but I am interesting what is the exact problem with the 1st implementation.

1.

public class Answer {
    static Map<Character, LinkedList<Character>> g = new HashMap<Character, LinkedList<Character>>();
    static Set<Character> visited = new HashSet<Character>();
    static ArrayList<Character> ans = new ArrayList<Character>();

    public static void dfs(char v) {
        visited.add(v);
        //some standard code for DFS
        ans.add(v);
    }

    public static String topologicalSort() {

        for (Character element : g.keySet()) {
            if (!visited.contains(element))
                dfs(element);
        }

        //some code to prepare the output
    }

    public static void builGraph(String[] words) {

        //some code to build adjacency list and then use it through g reference 
    }

    public static String answer(String[] words) {

        if (words.length == 1) {
            //some code
        }

        builGraph(words);

        return topologicalSort();
    }

    public static void main(String[] args) {
        //some code
        System.out.println(answer(words));
    } 
}

2.

public class Answer {
    static Map<Character, LinkedList<Character>> g;
    static Set<Character> visited;
    static ArrayList<Character> ans;

    public static void dfs(char v) {
        visited.add(v);
        //some standard code for DFS
        ans.add(v);
    }

    public static String topologicalSort() {
        visited = new HashSet<Character>();
        ans = new ArrayList<Character>();

        for (Character element : g.keySet()) {
            if (!visited.contains(element))
                dfs(element);
        }

        //some code to prepare the output
    }

    public static void builGraph(String[] words) {

        g = new HashMap<Character, LinkedList<Character>>();

        //some code to build adjacency list and then use it through g reference 
    }

    public static String answer(String[] words) {

        if (words.length == 1) {
            //some code
        }

        builGraph(words);

        return topologicalSort();
    }

    public static void main(String[] args) {
        //some code
        System.out.println(answer(words));
    } 
}

Upvotes: 2

Views: 147

Answers (2)

virtual agent 07
virtual agent 07

Reputation: 126

Where do you clear your containers (Map, Set, ArrayList) in the 1st implementation? A test case might call answer() multiple times, so I would change answer() method from the 1st implementation to something like:

public static String answer(String[] words) {
    this.g.clear();
    this.visited.clear();
    this.ans.clear();

    // ...
}

Upvotes: 1

Maroun
Maroun

Reputation: 95948

I don't know what the test is checking, so I don't know why it's failing. However, it's easy to tell the differences between the two implementations.

In Java (quoting the 4.12.5. Initial Values of Variables):

For all reference types (§4.3), the default value is null.

The objects in second case are assigned null until you initialize them, and you do that on each call of topologicalSort. So every time the method is called, a new object will be created.

In the first implementation, you only initialize them once - when the class is created. This should be enough for you to dig more into the problem and better understand why the test is failing in the first implementation.

Upvotes: 0

Related Questions