Logging and performance improvements to the item-item builder

This set of changes does a few things:

- Improve item-item builder logging
- Decrease memory allocation for sparsity (we iterate over all users' items with a `seen` set for deduplication, rather than building an RBTree)
- Make sparsity adaptive (if we have seen 75% of items, but still have 50% of users left to go, just use all the items)
- Use a provider rather than a factory to build the item-item build context
- Implement use of sparsity as a strategy (`NeighborIterationStrategy`), so that non-sparse iteration can be used even for sparse similarity functions. The default provider looks at the similarity function and decides which strategy to use.

This is ready for review once the tests pass.