# Map
Design and implement a `threadsafe` map. A key/value datastructure. It has the following properties
*Ofcourse use your own underlying datastructure (not the `map` itself. lol)*
- The keys are of any `comparable` type.
- The values can by of `any` type.
- Type checking is done at `compile-time`
- For example, consider the map `m = Map<int,int>` (pseudocode)
- Then, `m.put("string","string")` should fail at compile time.
## Creation
- You instantiate the map with the types of key and value. e.g `NewMap(int,int)` or `NewMap[int,int]()`, etc.. (it's up to you)
- If you like, the map can also take in a capacity argument.
## Get
Get gets a value from the map. `map.get(key)`
- It should return `value, exists` where `exists` is a boolean that is `true` if `value` exists in the map. Otherwise, its false and `value` is the default value for the type.
## Put
Put adds or updates an key/value pair in the map. `map.put(key,value)`
- If the key already exists, it updates its value.
- Else, adds a new pair.
- It does not return anything
## Delete
Delete removes the element associated with the key provided. `map.delete(key)`
- If the key does not exist, `delete` is a `no-op`.
- `delete` does not return anything.
## Length
Length returns the size of the map (the number of elements it contains)
### ForEach
`ForEach` applys the calls the func on every key/value pair in the map.
```go=
m.foreach(func(key,val) bool {
return true
})`
```
The boolen return determines whether to move to the next iteration or terminate the foreach.
## Functional programming (nice to have)
These are nice to have features
### Keys
`keys` returns a list of the keys in the map
```go=
keys = m.keys()
```
### Values
`values` returns a list of the values in the map
```go=
vals = m.values()
```
### Select
`Select` accepts a filter function and returns a list of values that pass the filter.
```go=
vals = m.select(func(key,val) bool {
// filter
return true
})
```