https://github.com/jerolba/bikey
Low memory footprint Map and Set implementation on objects with composited keys
https://github.com/jerolba/bikey
bikey collections java map set table
Last synced: 4 months ago
JSON representation
Low memory footprint Map and Set implementation on objects with composited keys
- Host: GitHub
- URL: https://github.com/jerolba/bikey
- Owner: jerolba
- License: apache-2.0
- Created: 2019-04-19T11:32:23.000Z (about 7 years ago)
- Default Branch: master
- Last Pushed: 2021-05-17T04:25:27.000Z (about 5 years ago)
- Last Synced: 2024-04-14T19:09:40.387Z (about 2 years ago)
- Topics: bikey, collections, java, map, set, table
- Language: Java
- Homepage:
- Size: 146 KB
- Stars: 14
- Watchers: 4
- Forks: 0
- Open Issues: 5
-
Metadata Files:
- Readme: README.md
- Contributing: CONTRIBUTING.md
- License: LICENSE.txt
- Code of conduct: CODE_OF_CONDUCT.md
Awesome Lists containing this project
README
[](https://maven-badges.herokuapp.com/maven-central/com.jerolba/bikey)
[](https://circleci.com/gh/jerolba/bikey)
[](https://bintray.com/jerolba/maven/bikey/_latestVersion)
[](https://codecov.io/gh/jerolba/bikey/)
[](http://www.apache.org/licenses/LICENSE-2.0.html)
[](https://javadoc.io/doc/com.jerolba/bikey)
Bikey
Bikey implements Map and Set data structures with two keys minimizing memory consumption.
## Why Bikey collections?
Current collections libraries ([Guava](https://github.com/google/guava), [Commons Collection](https://commons.apache.org/proper/commons-collections/), [Eclipse Collections](https://github.com/eclipse/eclipse-collections)) have poor or not support to Maps and Sets with two keys.
Implementing it manually with a `Map>`, `Map, V>` or a `Set>` consumes a lot of memory, and [choosing an incorrect hashCode function](https://medium.com/@jerolba/hashing-and-maps-87950eed673f) for Tuple (or equivalent) class can [penalize memory and CPU consumption](https://medium.com/@jerolba/composite-key-hashmaps-1422e2e6cdbc).
**Bikey Map collection can reduce to a 15%-30% of consumed memory** by a traditional double map (depending on the map _fill rate_) and **Bikey Set collection can reduce to a 1% of consumed memory by a Set\**, with none or low penalization in access time.
## Some Quick Examples
`BikeyMap` API is defined like the [Map](https://docs.oracle.com/javase/8/docs/api/java/util/Map.html) interface but everywhere a key is needed, you must provide both key values.
To simplify the example `String`s has been used as keys, but any object that implements `equals` and `hashCode` can be used as row or column key. You can also use any kind of object as value. I've used Integer to simplify the following code:
```java
BikeyMap stock = new TableBikeyMap<>();
stock.put("shirt-ref-123", "store-76", 10);
stock.put("pants-ref-456", "store-12", 24);
...
stock.put("tie-ref-789", "store-23", 2);
Integer available = stock.get("shirt-ref-1234", "store-45");
//Total stock in store-123
stock.entrySet().stream()
.filter(entry -> entry.getColumn().equals("store-123"))
.mapToInt(entry -> entry.getValue())
.sum();
//Total stock in pants-ref-457
stock.entrySet().stream()
.filter(entry -> entry.getRow().equals("pants-ref-457"))
.mapToInt(entry -> entry.getValue())
.sum();
//All products included
Set products = stock.rowKeySet();
//All stores included
Set stores = stock.columnKeySet();
//Contains a product and store?
if (stock.containsKey("tie-ref-789", "store-23")) {
....
}
//Get all product/stores presents in the map
BikeySet productStores = map.bikeySet();
//BikeySet also implements Set>
Set> productStoresSet = map.bikeySet();
//Get products and stores with stock
BikeySet withStock = stock.entrySet().stream()
.filter(entry -> entry.getValue() > 0)
.map(BikeyEntry::getKey)
.collect(BikeyCollectors.toSet());
//Do something with each element in the map
stock.forEach((product, store, units) -> {
System.out.println("Product " + product + " has " + units + " in store " + store);
});
```
`BikeySet` API is defined like the [Set](https://docs.oracle.com/javase/8/docs/api/java/util/Set.html) interface but everywhere an element is used, changes to two values:
```java
BikeySet avengerFilms = new TableBikeySet<>();
avengerFilms.add("Hulk", "The Avengers");
avengerFilms.add("Iron Man", "The Avengers");
avengerFilms.add("Thor", "Avengers: Age of Ultron");
avengerFilms.add("Thor", "Thor: Ragnarok");
avengerFilms.add("Captain America", "Avengers: Infinity War");
....
if (avengerFilms.contains("Iron Man", "Black Panther")) {
....
}
//Films in the Set
Set filmsInSet = avengerFilms.columnKeySet();
//Avengers in the Set
Set avengersInSet = avengerFilms.rowKeySet();
//Films with Iron Man
List ironManFilms = avengerFilms.stream()
.filter(entry -> entry.getRow().equals("Iron Man"))
.map(Bikey::getColumn)
.collect(toList());
//Call to a BiFunction for each element in the Set
bikeySet.forEach(this::doSomething);
public void doSomething(String avenger, String film) {
....
}
```
## Implementations
`BikeyMap` has two implementations:
- `TableBikeyMap`: optimized for memory consumption, and with performance similar to a double map or tuple map version.
- `MatrixBikeyMap
com.jerolba
bikey
0.9.0
```
in Gradle:
`implementation 'com.jerolba:bikey:0.9.0'`
or download the single [jar](http://central.maven.org/maven2/com/jerolba/bikey/0.9.0/bikey-0.9.0.jar) from Maven Central Repository.
## Benchmarks
Execute your own benchmarks before deciding to use this library, but as a reference you can start with these numbers:
### Memory
Compared to `Map>` and `Map, V>`, the memory consumed filling a map with 10.000 x 1.000 elements is:

Compared to `HashMap>` and `HashSet>` implementations, the memory consumed filling a Set with 10.000 x 1.000 elements is:

### Performance
To create and fill randomly different maps in each implementation, the time spent is:

To find randomly different maps in each implementation, the time spent is:

To create and fill randomly a Set with 10.000 x 1.000 elements, the time spent is:

To check randomly the existence of each element in a Set with 10.000 x 1.000 elements, the time spent is:
## Contribute
Feel free to dive in! [Open an issue](https://github.com/jerolba/bikey/issues/new) or submit PRs.
Any contributor and maintainer of this project follows the [Contributor Covenant Code of Conduct](https://github.com/jerolba/bikey/blob/master/CODE_OF_CONDUCT.md).
## License
[Apache 2](https://github.com/jerolba/bikey/blob/master/LICENSE.txt) © Jerónimo López