Search code examples
javapythonarraylistsetinternals

Add List to Set is Possible in Java but not in Python?


I am new to Python and just stumbled on adding list to set. Now I know the reason why this is not possible is that list is mutable so its hashcode (or the Python corresponding concept) will change. Reflecting on my programming in Java, I found that I have done this many times.

HashSet<ArrayList<String>> masterCollection = new HashSet<ArrayList<String>>();
ArrayList<String> a = new ArrayList<String>();
masterCollection.add(a);
a.add("Hello, World");
for(ArrayList<String> list : masterCollection) {
    // do something to list
}

I did not notice any abnormal behaviors of the above code. I even used ArrayList as keys to HashMap and succeeded in accomplishing my task.

Therefore, I want to ask how internally Python is different in Java in this aspect and whether there are something I need to pay attention to when writing the above code.


Solution

  • Lists are unhashable in python because they do not define __hash__. There are reasons for that, but you could conceivably define your own mutable class that does, provided that said hash does not change across the lifetime of the object. For example, using id(x) as the hash. In fact, you've probably unknowingly implemented exactly that in a lot of your own classes.

    I'll quote from the docs on "hashable":

    All of Python’s immutable built-in objects are hashable, while no mutable containers (such as lists or dictionaries) are. Objects which are instances of user-defined classes are hashable by default; they all compare unequal (except with themselves), and their hash value is their id().

    Mutability and hashability are coupled, but not at all the same thing.