Fix two major bugs

First, JobProgessListener uses HashSets of TaskInfo and StageInfo, and relies on the equality
of these objects to remove from the corresponding HashSets correctly. This is not a luxury that
deserialized StageInfo's and TaskInfo's have. Instead, when removing from these collections, we
must match by the ID rather than the object itself.

Second, although SparkUI differentiates between persisted and live UI's, its children UI's and
their corresponding listeners do not. Thus, each revived UI essentially duplicated all the logs
that reconstructed it in the first place. Further, these zombie UI's continued to respond to
live SparkListenerEvents. This has been fixed by requiring that revived UI's do not register
their listeners with the current SparkContext.

With the former fix, there were major incompatibility issues with the existing way UI classes
access and mutate the collections. Formatting improvements associated with smoothing out these
inconsistencies are included as part of this commit.