Skip to content

Optimized quad tree and cluster algorithm with HashSet instead of ArrayList #368

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Apr 17, 2018

Conversation

jeffdgr8
Copy link
Contributor

ArrayList.remove() is a much more expensive operation than HashSet.remove(). Neither of these collections need to be an array, as neither order nor duplicate entries are required. A set collection is much more optimal with very noticeable speed improvements with large sets of cluster items.

…yList

ArrayList.remove() is a much more expensive operation than
HashSet.remove(). Neither of these collections need to be an array, as
neither order nor duplicate entries are required. A set collection is
much more optimal with very noticeable speed improvements with large
sets of cluster items.
@jeffdgr8 jeffdgr8 changed the title Optimzed quad tree and cluster algorithm with HashSet instead of ArrayList Optimized quad tree and cluster algorithm with HashSet instead of ArrayList Feb 27, 2017
@barbeau
Copy link
Collaborator

barbeau commented Mar 1, 2017

Huge +1 for this as long as it doesn't affect algorithm correctness. It changes time complexity from O(n) to O(1) for remove() operation (assuming HashSet is implemented optimally by the platform).

I've run the tests locally and they all pass, and while it's been a while since I've done a deep dive on QuadTrees, I don't believe changing from a List to a Set has any adverse side-effects.

I'd like to get another set of eyes on this that's familiar with QuadTrees before merging though.

@broady
Copy link
Contributor

broady commented Mar 1, 2017

This looks fine, but I can't recall if iteration order ever matters (use TreeSet instead, then).

Does this actually improve performance noticeably, though? MAX_ELEMENTS=50, so you should only be iterating over 50 elements.

This might not be true if MAX_DEPTH is reached.

@barbeau
Copy link
Collaborator

barbeau commented Mar 1, 2017

From a quick look through the code it doesn't appear that order matters - only operations used are add and remove with simple iterations though collection.

@jeffdgr8
Copy link
Contributor Author

There's a very noticeable speed improvement in our use case where we have potentially 10,000+ markers on the map at times. When toggling them on/off the ArrayList.remove() operation was the clear bottleneck.

@AAverin
Copy link

AAverin commented Oct 3, 2017

Sad, such a nice PR not merged because emulator couldn't start on travis

@jeffdgr8
Copy link
Contributor Author

jeffdgr8 commented Nov 8, 2017

@broady @barbeau @stephenmcd @markmcd any chance we can get this as well as my other PRs #337 #339 #378 #380 #381 merged? These along with this PR #217 have been functioning great in our production app for a long time now using my fork. https://github.com/jeffdgr8/android-maps-utils/tree/sales-rabbit It'd be great to have these fixes finally in the main repo.

@stephenmcd stephenmcd merged commit bb052f0 into googlemaps:master Apr 17, 2018
@stephenmcd
Copy link
Contributor

Thanks a lot

@jeffdgr8 jeffdgr8 deleted the quad-tree-optimizations branch June 26, 2018 04:12
arriolac pushed a commit that referenced this pull request Feb 17, 2020
A clustering performance improvement was made in #368 by switching from using an ArrayList to a HashSet. However, ArrayLists maintain insertion order of the elements when iterating over them later, while HashSets do not. Because the cluster has the center of the first element, that center will change if the iteration order of the elements change, which results in clusters changing position when updating an item model and reclustering.

This changes to using a LinkedHashSet, which should give the same constant time performance benefits as the Set for add/remove over the List, but still maintains insertion order.

A unit test for insertion order is also added.

Fixes #615

Refs: 615
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants