Skip to content

Commit d7e2d9f

Browse files
ragnesebalazstothofficial
authored andcommitted
More efficient implementations of NonEmptySet and NonEmptyMap, and the plus operators.
1 parent 88b0fcd commit d7e2d9f

4 files changed

Lines changed: 40 additions & 61 deletions

File tree

Lines changed: 9 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,29 @@
11
package com.quickbirdstudios.nonEmptyCollection.map
22

3-
operator fun <K, V> NonEmptyMap<K, V>.plus(entry: Pair<K, V>) = copy(rest = rest + entry)
3+
import kotlin.collections.plus as stdPlus
44

5-
operator fun <K, V> Map<K, V>.plus(entry: Pair<K, V>) = run {
6-
val first = entries.first()
5+
operator fun <K, V> NonEmptyMap<K, V>.plus(entry: Pair<K, V>): NonEmptyMap<K, V> = full + entry
76

8-
NonEmptyMap(
9-
first = first.key to first.value,
10-
rest = this + mapOf(entry) - first.key
11-
)
12-
}
7+
operator fun <K, V> Map<K, V>.plus(entry: Pair<K, V>): NonEmptyMap<K, V> = NonEmptyMap(this.stdPlus(entry))
138

14-
operator fun <K, V> NonEmptyMap<K, V>.plus(other: Map<K, V>) = copy(rest = rest + other)
9+
operator fun <K, V> NonEmptyMap<K, V>.plus(other: Map<K, V>): NonEmptyMap<K, V> = NonEmptyMap(full.stdPlus(other))
1510

1611
operator fun <K, V> Map<K, V>.plus(
1712
other: NonEmptyMap<K, V>
18-
): NonEmptyMap<K, V> = other + this
13+
): NonEmptyMap<K, V> = NonEmptyMap(this.stdPlus(other.full))
1914

2015
operator fun <K, V> NonEmptyMap<K, V>.plus(
2116
other: NonEmptyMap<K, V>
22-
): NonEmptyMap<K, V> = this as Map<K, V> + other
17+
): NonEmptyMap<K, V> = full + other
2318

2419
operator fun <K, V> NonEmptyMap<K, V>.plus(
2520
other: Iterable<Pair<K, V>>
26-
): NonEmptyMap<K, V> = this + other.toMap()
21+
): NonEmptyMap<K, V> = NonEmptyMap(full.stdPlus(other))
2722

2823
operator fun <K, V> NonEmptyMap<K, V>.plus(
2924
other: Sequence<Pair<K, V>>
30-
): NonEmptyMap<K, V> = this + other.toMap()
25+
): NonEmptyMap<K, V> = NonEmptyMap(full.stdPlus(other))
3126

3227
operator fun <K, V> NonEmptyMap<K, V>.plus(
3328
other: Array<Pair<K, V>>
34-
): NonEmptyMap<K, V> = this + other.toMap()
29+
): NonEmptyMap<K, V> = NonEmptyMap(full.stdPlus(other))
Lines changed: 11 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,18 @@
11
package com.quickbirdstudios.nonEmptyCollection.map
22

3-
import com.quickbirdstudios.nonEmptyCollection.NonEmptyCollection
4-
import com.quickbirdstudios.nonEmptyCollection.set.NonEmptySet
5-
import com.quickbirdstudios.nonEmptyCollection.unsafe.UnsafeNonEmptyCollectionApi
6-
import com.quickbirdstudios.nonEmptyCollection.unsafe.toNonEmptyList
7-
import com.quickbirdstudios.nonEmptyCollection.unsafe.toNonEmptySet
8-
9-
data class NonEmptyMap<K, V> internal constructor(
10-
internal val first: Pair<K, V>,
11-
internal val rest: Map<K, V>
12-
) : Map<K, V> by mapOf(first) + rest {
13-
14-
private val map by lazy {
15-
mapOf(first) + rest
3+
class NonEmptyMap<K, out V> internal constructor(internal val full: Map<K, V>) : Map<K, V> by full {
4+
constructor(
5+
first: Pair<K, V>,
6+
rest: Map<K, V>
7+
) : this(LinkedHashMap<K, V>(rest.size + 1).apply { put(first.first, first.second); putAll(rest) })
8+
9+
init {
10+
require(full.isNotEmpty()) { "Fatal Error! This is a bug. Please contact the library author." }
1611
}
1712

18-
@OptIn(UnsafeNonEmptyCollectionApi::class)
19-
override val entries: NonEmptySet<Map.Entry<K, V>>
20-
get() = map.entries.toNonEmptySet()
21-
22-
@OptIn(UnsafeNonEmptyCollectionApi::class)
23-
override val keys: NonEmptySet<K>
24-
get() = map.keys.toNonEmptySet()
25-
26-
@OptIn(UnsafeNonEmptyCollectionApi::class)
27-
override val values: NonEmptyCollection<V>
28-
get() = map.values.toNonEmptyList()
29-
30-
override fun equals(other: Any?): Boolean = toMap() == other
13+
override fun toString(): String = full.toString()
3114

32-
override fun hashCode(): Int = toMap().hashCode()
15+
override fun equals(other: Any?): Boolean = full == other
3316

17+
override fun hashCode(): Int = full.hashCode()
3418
}
Lines changed: 9 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,29 @@
11
package com.quickbirdstudios.nonEmptyCollection.set
22

3-
operator fun <T> NonEmptySet<T>.plus(value: T) = copy(rest = rest + value)
3+
import kotlin.collections.plus as stdPlus
44

5-
operator fun <T> Set<T>.plus(value: T) = run {
6-
val first = firstOrNull() ?: value
5+
operator fun <T> NonEmptySet<T>.plus(value: T): NonEmptySet<T> = full + value
76

8-
NonEmptySet(
9-
first = first,
10-
rest = (this.plusElement(value)) - first
11-
)
12-
}
7+
operator fun <T> Set<T>.plus(value: T): NonEmptySet<T> = NonEmptySet(this.stdPlus(value))
138

14-
operator fun <T> NonEmptySet<T>.plus(other: Set<T>) = copy(rest = rest union other)
9+
operator fun <T> NonEmptySet<T>.plus(other: Set<T>) = NonEmptySet(full.stdPlus(other))
1510

1611
operator fun <T> Set<T>.plus(
1712
other: NonEmptySet<T>
18-
): NonEmptySet<T> = other + this
13+
): NonEmptySet<T> = NonEmptySet(this.stdPlus(other.full))
1914

2015
operator fun <T> NonEmptySet<T>.plus(
2116
other: NonEmptySet<T>
22-
): NonEmptySet<T> = this as Set<T> + other
17+
): NonEmptySet<T> = this + other.full
2318

2419
operator fun <T> NonEmptySet<T>.plus(
2520
other: Iterable<T>
26-
): NonEmptySet<T> = this + other.toSet()
21+
): NonEmptySet<T> = NonEmptySet(full.stdPlus(other))
2722

2823
operator fun <T> NonEmptySet<T>.plus(
2924
other: Sequence<T>
30-
): NonEmptySet<T> = this + other.toSet()
25+
): NonEmptySet<T> = NonEmptySet(full.stdPlus(other))
3126

3227
operator fun <T> NonEmptySet<T>.plus(
3328
other: Array<T>
34-
): NonEmptySet<T> = this + other.toSet()
29+
): NonEmptySet<T> = NonEmptySet(full.stdPlus(other))

src/commonMain/kotlin/com/quickbirdstudios/nonEmptyCollection/set/NonEmptySet.kt

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,17 @@ package com.quickbirdstudios.nonEmptyCollection.set
22

33
import com.quickbirdstudios.nonEmptyCollection.NonEmptyCollection
44

5-
data class NonEmptySet<T> internal constructor(
6-
internal val first: T,
7-
internal val rest: Set<T>
8-
) : Set<T> by rest.plusElement(first), NonEmptyCollection<T> {
5+
class NonEmptySet<T> internal constructor(
6+
internal val full: Set<T>
7+
) : Set<T> by full, NonEmptyCollection<T> {
8+
constructor(
9+
first: T,
10+
rest: Set<T>
11+
) : this(HashSet<T>(rest.size + 1).apply { add(first); addAll(rest) })
912

10-
override fun equals(other: Any?): Boolean = toSet() == other
13+
override fun toString(): String = full.toString()
1114

12-
override fun hashCode(): Int = toSet().hashCode()
15+
override fun equals(other: Any?): Boolean = full == other
16+
17+
override fun hashCode(): Int = full.hashCode()
1318
}

0 commit comments

Comments
 (0)