VahidB
VahidB

Reputation: 145

difference between .contains() and .keySet.exists() in Scala Maps

I have a map var surfaceMap = Map[Surface, Array[Event]]() in Scala where Surface class represents geometrical surfaces consisting of planes. In Surface class I define equals method as follows:

final override def equals(other: Any): Boolean = other match {
    case that: Surface => (planes.deep == that.planes.deep) 
    case _ => false
}
final override def hashCode: Int = planes.##

The equality checks if all the planes that construct the surface has the same coordinates. I have a surfaceMap of 8 elements and when I want to add an Event to a surface that is already in the map, when I check the existence of the key with surfaceMap.contains(newSurface) it returns false but when I use surfaceMap.exists(_._1 == newSurface) or surfaceMap.keySet.exists(_ == newSurface) it takes longer and returns true. I thought .contains() and .keySet.exists() do the same job but it seems that they are different but I don't understand the difference. Any help is appreciated.

Upvotes: 1

Views: 4043

Answers (1)

Dima
Dima

Reputation: 40500

Map.keySet.exists does not do the same thing as Map.contains, Map.keySet.contains does.

The difference is that .contains uses object's hash code (provided, we are using the default, HashMap, implementation) to quickly navigate to the key you are looking for. This is a constant time (O(1)) operation.

.exists cannot do that, because it is looking for an arbitrary condition, not an exact object. So, it has to scan the entire set and evaluate the condition for each element, until it finds the one that matches. This is a linear time (O(N)) operation.

As to why Map.contains returns false in your case, that must be because your hashCode implementation is incorrect: you are using the default .##, which will be different for different instances, even if they contain the same values (unless, it is a case class).

Upvotes: 5

Related Questions