Clean up CandidateMatcher API

There was lots of repeated code in the various CandidateMatcher implementations.
This commit moves all that into CandidateMatcher itself, as well as replacing
the (incorrect!) HashSet container in SimpleMatcher for a Map keyed on the query
string.