Skip to content

Use a bimap for reverse lookups on injective maps#5681

Merged
drcrallen merged 3 commits intoapache:masterfrom
dylwylie:lookup-bimap
May 8, 2018
Merged

Use a bimap for reverse lookups on injective maps#5681
drcrallen merged 3 commits intoapache:masterfrom
dylwylie:lookup-bimap

Conversation

@dylwylie
Copy link
Copy Markdown
Contributor

  • A BiMap provides constant-time lookups for mapping values to keys

Using this as an excuse to play around with the code, comments welcome!

- A BiMap provides constant-time lookups for mapping values to keys
if (this.map instanceof HashBiMap) {
return Lists.newArrayList(((HashBiMap<String, String>) this.map).inverse().get(value));
} else {
return Lists.newArrayList(Maps.filterKeys(map, new Predicate<String>()
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(minor) can this use java 8 lambdas like

key -> map.get(key).equals(Strings.nullToEmpty(value))

?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

{
this.map = Preconditions.checkNotNull(map, "map");
this.isOneToOne = isOneToOne;
this.map = Preconditions.checkNotNull(this.isOneToOne ? HashBiMap.create(map) : map, "map");
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like HashBiMap#inverse creates a new object in a not thread safe manner, but the object is pretty light weight. Due to the nature of lookups this might cause a thundering of racy objects, which should be benign since the map is immutable, but annoying. Would it make sense to create the inverse map as a Map<String, String> eagerly, and null the object if not one-to-one, then in the unapply simply check for the eager inverse map being non null and do a Collections.singletonList on the result, if it exists?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice catch - thanks!

{
@Override public boolean apply(@Nullable String key)
if (this.map instanceof HashBiMap) {
return Lists.newArrayList(((HashBiMap<String, String>) this.map).inverse().get(value));
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

from the Interface docs:

   * @return the list of keys that maps to value or empty list.
   * Note that for the case of a none existing value in the lookup we have to cases either return an empty list OR list with null element.
   * returning an empty list implies that user want to ignore such a lookup value.
   * In the other hand returning a list with the null element implies user want to map the none existing value to the key null.

I'm actually not 100% sure which one should be done here, @b-slim do you have any insight for this?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've modified to match what the existing implementation and other interface implementations (I think) do.

@dylwylie
Copy link
Copy Markdown
Contributor Author

Hmm realise this might be naive, if we get passed in something like a MapDB offheap htreemap we'd be defeating the point of the off-heap collection by copying everything into the inverse offheap.

Wondering about letting the caller pass in the reverse map.

@drcrallen drcrallen added this to the 0.13.0 milestone May 8, 2018
@drcrallen drcrallen merged commit e1277d3 into apache:master May 8, 2018
sathishsri88 pushed a commit to sathishs/druid that referenced this pull request May 8, 2018
* Use a bimap for reverse lookups on injective maps

- A BiMap provides constant-time lookups for mapping values to keys

* Address comments

* Fix Tests
@dylwylie
Copy link
Copy Markdown
Contributor Author

dylwylie commented May 9, 2018

Reverting this, the following code passes in an offHeap backed map from MapDb, so we'd inadvertently be copying all of its data onHeap when creating the BiMap

https://github.com/druid-io/druid/blob/5929066dfba96c918f14e26b629534f53de0f9cd/extensions-core/lookups-cached-global/src/main/java/io/druid/query/lookup/NamespaceLookupExtractorFactory.java#L216

jon-wei pushed a commit that referenced this pull request May 10, 2018
* Revert "Consider waiting and pending compaction tasks as well as running tasks in DruidCoordinatorSegmentCompactor (#5704)"

This reverts commit c7a5939.

* Revert "Fix metrics for inserting segments (#5749)"

This reverts commit c9d6451.

* Revert "Typo fix in historical doc (#5753)"

This reverts commit aa23fe6.

* Revert "Use a bimap for reverse lookups on injective maps (#5681)"

This reverts commit e1277d3.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants