kounter

Counting easily with Kotlin

License

License

GroupId

GroupId

com.github.pgreze
ArtifactId

ArtifactId

kounter
Last Version

Last Version

1.4
Release Date

Release Date

Type

Type

pom.sha512
Description

Description

kounter
Counting easily with Kotlin
Project URL

Project URL

https://github.com/pgreze/kounter
Source Code Management

Source Code Management

https://github.com/pgreze/kounter

Download kounter

Dependencies

runtime (1)

Group / Artifact Type Version
org.jetbrains.kotlin : kotlin-stdlib-jdk8 jar 1.4.30

Project Modules

There are no modules declared in this project.

Kounter License Build codecov

Choose the easy-to-use Counter or the fully flexible MapWithDefault.

Installation central

dependencies {
    // Check the ๐Ÿ” maven central badge ๐Ÿ” for the latest $version
    implementation("com.github.pgreze:kounter:$version")
}

repositories {
    jcenter()
}

Usage

Counter / MutableCounter

A specialization of the Map class allowing to count objects.
This is similar to Guava Multiset or Python Counter, inspired by older references like Smalltalk Bag class.

Usage:

val lints = mutableCounterOf("warnings" to 20)

lints["warnings"] += 3
lints["errors"] += 1

println(lints) // {warnings=23, errors=1}

Helpers:

counterOf("aabbbcc")                    // {a=2, b=3, c=2}
counterOf(arrayOf('a', 'b', 'b', 'c'))  // {a=1, b=2, c=1}
counterOf(listOf('a', 'a', 'b', 'c'))   // {a=2, b=1, c=1}
counterOf(setOf('a', 'b', 'c'))         // {a=1, b=1, c=1}

To perform mathematical operations on counters, use following methods:

val c1 = counterOf("ab")
val c2 = counterOf("ccd")
c1.plusAll(c2) // {a=2, b=3, c=2}

val chars = mutableCounterOf("ab")
chars.addAll(counterOf("ccd")) // {a=2, b=3, c=2}

MapWithDefault / MutableMapWithDefault

Counter / MutableCounter are internally using these classes.

There are also an alternative of withDefault which is a memory efficient way to specify a default value for a Map but sadly, not reflecting this change in its signature.
It's forcing users to use an unnatural getValue extension method, which is not the most intuitive way of using a Map.

Proposed alternative is slightly changing the original Map interface:

interface MapWithDefault<K, V> : Map<K, V> {
    override fun get(key: K): V
}

Allowing to unlock a better syntax:

val money = mutableMapOf("Alice" to 5)
    .setDefault { 0 }

money["Alice"] += 10
money["Bob"] += 3

println(money) // {Alice=15, Bob=3}

Which is shining when used with Set/List/Map:

val sets = mutableMultiSetWithDefaultOf<String, String>()
// Alias for mutableMapOf<String, Set<String>>().setDefault { setOf() }

sets += "Alice" to setOf("f1.txt")
sets["Bob"] += setOf("f2.md")

println(sets) // {"A0"= setOf("f1.txt"), "A1"= setOf("f2.md")}

Following helpers are available for common native collections:

+ setDefault Mutable + setDefault
List multiListWithDefaultOf mutableMultiListWithDefaultOf
Set multiSetWithDefaultOf mutableMultiSetWithDefaultOf
Map multiMapWithDefaultOf mutableMultiMapWithDefaultOf

Alternative: Guava collection package including Multimap implemented by ListMultimap or SetMultimap.

Versions

Version
1.4