HashMap based on Eq and Object#hashCode#304
Conversation
Codecov Report
@@ Coverage Diff @@
## master #304 +/- ##
==========================================
- Coverage 91.56% 90.67% -0.90%
==========================================
Files 24 24
Lines 1625 1641 +16
Branches 214 211 -3
==========================================
Hits 1488 1488
- Misses 137 153 +16
Continue to review full report at Codecov.
|
|
How do I add tests? |
|
Hi @sorenbug and thanks for your contribution! The current set/map files should really be prefixed with As for your contribution, I recommend putting them into separate files, such as To write tests, I think you could largely copy the existing tests and change occurrences of |
|
Sounds good! I will do so. |
|
Also, @sorenbug I think we'd want to require https://github.com/typelevel/cats/blob/master/kernel/src/main/scala/cats/kernel/Hash.scala We don't want to use universal hashing Lastly, getting a high performance HashMap will be a bit tricky, but I think directly implementing this via the HAMT approach: vs using a Vector, will be more performant, but maybe not... it will be fine. In any case, if we make the details private, we can merge it with the right API and optimize later. I think we want a minimal API and as much as possible private. Something like: trait HashMap[K, +V] {
def get(k: K)(implicit hash: Hash[K]): Option[V]
def updated[V1 >: V](k: K, v: V1)(implicit hash: Hash[K]): HashMap[K, V1]
// return the given value of the key and the state of the map without it
def take(k: K)(implicit hash: Hash[K]): (Option[V], HashMap[K, V])
def length: Long
def iterator: Iterator[(K, V)]
// without having to hash the key twice, transform a given key
def transformKey[R, V1 >: V](k: K)(fn: Option[V1] => (R, Option[V1])): (R, HashMap[K, V1])
// transform the values with the key given as input,but we cannot change the key
// this can be faster since you don't change the structure or rehash the keys
def mapWithKey[V1](fn: (K, V) => V1): HashMap[K, V1]
}
object HashMap {
def empty[K, V]: HashMap[K, V]
} |
|
Ah! I couldn't find a Re HAMT: I didn't know how to make a HashMap so I just copied a Java example I found online. I'll check it out. |
|
So, the new typeclass dependencies for some things seem a little odd. I haven't implemented a HAMT as of yet, but that'll be next. I'd like a review on my usage of |
|
The Wikipedia page is not helping for how to implement a HAMT, and my data structures course has nothing on it. What should I look at to implement one? |
Codecov Report
@@ Coverage Diff @@
## master #304 +/- ##
==========================================
- Coverage 91.37% 89.61% -1.77%
==========================================
Files 24 26 +2
Lines 1623 1656 +33
Branches 216 215 -1
==========================================
+ Hits 1483 1484 +1
- Misses 140 172 +32
Continue to review full report at Codecov.
|
|
@sorenbug Thanks for following up! From my PoV, this implementation is ready for review (even without a HAMT implementation). Only thing missing now is tests for HashSet and HashMap. Ideally, the ones from AvlSet and AvlMap can be copied. |
|
Alright, I learned how to make a HAMT: It seems like I'd want to basically copy stdlib's The current implementation has O(n) lookup because there's no resizing logic, and it's not a good implementation for an immutable HashMap anyways: usually this implementation is used for mutable HashMaps, even though adding an element is O(1). |
|
I am closing this due to #534 but I appreciate you starting the ball rolling. If you are still interested, I think there are still optimization opportunities in the hashmap code that was merged. |
|
Yeah, as much as I wanted to finish this up I never really got around to understanding how to make better HashMaps. Thanks for keeping up with things! |
For when there's an
Eqwith noOrder. I'm not the best at designing HashMaps nor cats-centric collections; I'm opening as a draft PR in hopes of live feedback.