Why do Kotlin Sets have indices? - kotlin

I'm curious as to why Kotlin Sets have indices. You can access elements by using mySet.elementAt(index). No other language I know has this feature. Is the feature any useful if sets aren't supposed to be ordered and yet they have indices? Also, doesn't this feature make Sets in Kotlin slower than other Sets in other languages?

Set has the elementAt method, not because it is based on indices (so it is not "slower than other languages" just because it has this method), but because it implements Iterable<T>. elementAt is an extension function on Iterable<T>:
fun <T> Iterable<T>.elementAt(index: Int): T
What a Set is based on depends on which concrete implementation of Set you use (Set is just an interface). HashSet is based on a hash table, for example.
So Set gets this elementAt method "for free" just because it implements Iterable<T>. The only way for it to not have elementAt is to not implement Iterable<T>, but that would mean you can't iterate over a Set. That's not very useful, is it? Also, as I'll talk about later, elementAt does have its uses.
Since elementAt is an extension function on Iterable<T>, all it can do really, is to ask to the iterator to give it n elements, and return the last element. This is how it is implemented.
public fun <T> Iterable<T>.elementAt(index: Int): T {
if (this is List)
return get(index)
return elementAtOrElse(index) { throw IndexOutOfBoundsException("Collection doesn't contain element at index $index.") }
}
...
public fun <T> Iterable<T>.elementAtOrElse(index: Int, defaultValue: (Int) -> T): T {
if (this is List)
return this.getOrElse(index, defaultValue)
if (index < 0)
return defaultValue(index)
val iterator = iterator()
var count = 0
while (iterator.hasNext()) {
val element = iterator.next()
if (index == count++)
return element
}
return defaultValue(index)
}
If your Set does not have a particular order (e.g. HashSet), then its iterator will return elements in no particular order either, so using elementAt(x) is not very meaningful. On the other hand, if you are using an ordered set, like a LinkedHashSet (this is what setOf and mutableSetOf creates), then using elementAt does make sense.
Also note that elementAt does have O(n) time, but that doesn't mean that accessing the set using the set's methods (e.g. contains) also has O(n) time. That also depends on which concrete implementation of Set you use. Both LinkedHashSet.contains and HashSet.contains are O(1) time.

Related

Are any{}, all{}, and none{} lazy operations in Kotlin?

I am using a functional programming style to solve the Leetcode easy question, Count the Number of Consistent Strings. The premise of this question is simple: count the amount of values for which the predicate of "all values are in another set" holds.
I was able to do this pretty concisely like so:
class Solution {
fun countConsistentStrings(allowed: String, words: Array<String>): Int {
val permitted = allowed.toSet()
return words.count{it.all{it in permitted}}
}
}
I know that Java streams are lazy, but have read Kotlin is only lazy when asSequence is used and are otherwise eager.
For reductions to a boolean based on a predicate using any, none, or all, it makes the most sense to me that this should be done lazily (e.g. a single false in all should evaluate the whole expression to false and stop evaluating the predicate for other elements).
Are these operations implemented this way, or are they still done eagerly like other operations in Kotlin. If so, there a way to do them lazily?
No, those methods are not lazy.
First, bear in mind that there are multiple methods with each of those names: two defined on Sequence, two defined on each of thirteen types of array, two on Map, and one on Iterable. It's clear you're interested only in those defined on Sequence, as those other types don't support laziness.
So, let's look at the docs! The docs for Sequence.any(), for Sequence.none(), and for Sequence.all() methods all say:
The operation is terminal.
To confirm what this means, the docs for the kotlin.sequences package, say:
If the sequence operation returns another sequence, which is produced lazily, it's called intermediate, and otherwise the operation is terminal.
So those methods are not lazy; when executed, they cause the sequence to be evaluated as far as is needed to produce the required value. (However, they don't evaluate it any further than is needed, which may be what you're asking. After all, that's the point of using Sequences!)
(In fact, you can see from their types that there's no way they could be lazy: each of them returns a Boolean value, which is either true or false. To support lazy evaluation, they'd need to return a Future or similar object with a getter that could be called to produce a final result. But a Boolean already is that final result.)
I think you overinterpret what lazily and eagerly mean. Like "eagerly" means to always do everything in the most inefficient way possible.
Lazy collections (Streams API, sequences) try to postpone calculating their contents until necessary. On the other hand regular collections perform operations immediately when requested. But that doesn't mean if we ask a regular collection for its first element, it will iterate over all of them for no reason.
As a matter of fact, these functions are implemented in almost exactly the same way for both iterables and sequences. The difference is in other transformations and operators. Below is an example for any():
public inline fun <T> Iterable<T>.any(predicate: (T) -> Boolean): Boolean {
if (this is Collection && isEmpty()) return false
for (element in this) if (predicate(element)) return true
return false
}
public inline fun <T> Sequence<T>.any(predicate: (T) -> Boolean): Boolean {
for (element in this) if (predicate(element)) return true
return false
}
The docs don't explicitly say, but this is easy enough to test.
class A : Iterable<String>, Iterator<String> {
public override fun iterator(): Iterator<String> {
return this
}
public override fun hasNext(): Boolean {
return true
}
public override fun next(): String {
return "test"
}
}
fun main(args: Array<String>) {
val a = A()
println(a.any { x -> x == "test" })
println(a.none { x -> x == "test" })
println(a.all { x -> x != "test" })
}
Here, A is a silly iterable class that just produces "test" forever and never runs out. Then we use any, none, and all to check whether it produces "test" or not. It's an infinite iterable, so if any of these three functions wanted to try to exhaust it, the program would hang forever. But you can run this yourself, and you'll see a true and two false's. The program terminates. So each of those three functions stopped when it found, respectively, a match, a non-match, and a non-match.
Try it online!
In short, Sequences in Kotlin are somewhat similar to Java Streams in that they have many lazy functions that simply return another Sequence.
However, all, any and none are immediate regardless of whether you call them on a Sequence or an Iterable. You can tell they are not lazy because they return a Boolean instead of another Sequence, and in their documentation, they are described as terminal, which means they evaluate and iterate the Sequence immediately.

Kotlin Interface method abstraction

I'm exploring the Substitution principal and from what I've understood about the principal is that a sub type of any super type should be passable into a function/class. Using this idea in a new section of code that I'm writing, I wanted to implement a abstract interface for a Filter like so
interface Filter {
fun filter(): Boolean
}
I would then imagine that this creates the contract for all classes that inherit this interface that they must implement the function filter and return a boolean output. Now my interpretation of this is that the input doesn't need to be specified. I would like it that way as I want a filter interface that guarantee the implementation of a filter method with a guarantee of a return type boolean. Does this concept even exists in Kotlin? I would then expect to implement this interface like so
class LocationFilter {
companion object : Filter {
override fun filter(coord1: Coordinate, coord2: Coordinate): Boolean {
TODO("Some business logic here")
}
}
}
But in reality this doesn't work. I could remove remove the filter method from the interface but that just defeats the point of the whole exercise. I have tried using varargs but again that's not resolving the issue as each override must implement varargs which is just not helpful. I know this may seem redundant, but is there a possibility to have the type of abstraction that I'm asking for? Or am I missing a point of an Interface?
Let's think about it a little. The main point of abstraction is that we can use Filter no matter what is the implementation. We don't need to know implementations, we only need to know interfaces. But how could we use Filter if we don't know what data has to be provided to filter? We would need to use LocationFilter directly which also defeats the point of creating an interface.
Your problem isn't really related to Kotlin, but to OOP in general. In most languages it is solved by generics/templates/parameterized types. It means that an interface/class is parameterized by another type. You use it in Kotlin like this:
interface Filter<in T> {
fun filter(value: T): Boolean
}
object LocationFilter : Filter<Coordinate> {
override fun filter(value: Coordinate): Boolean {
TODO()
}
}
fun acquireCoordinateFilter(): Filter<Coordinate> = LocationFilter
fun main() {
val coord: Coordinate = TODO()
val filter: Filter<Coordinate> = acquireCoordinateFilter()
val result = filter.filter(coord)
}
Filter is parameterized, meaning that we can have a filter for filtering strings (type is: Filter<String>), for filtering integers (Filter<Int>) or for filtering coordinates (Filter<Coordinate>). Then we can't use e.g. Filter<String> to filter integers.
Note that the code in main() does not use LocationFilter directly, it only knows how to acquire Filter<Coordinate>, but the specific implementation is abstracted from it.
Also note there is already a very similar interface in Java stdlib. It is called Predicate.
my interpretation of this is that the input doesn't need to be specified.
Where did you get that interpretation from?
You can see that it can't be correct, by looking at how the method would be called.  You should be able to write code that works for any instance of Filter — and that can only happen if the number and type of argument(s) is specified in the interface.  To use your example:
val f: Filter = someMethodReturningAFilterInstance()
val result = f.filter(coord1, coord2)
could only work if all implementations used two Coordinate parameters. If some used one String param, and others used nothing at all, then how would you call it safely?
There are a few workarounds you could use.
If every implementation takes the same number of parameters, then you could make the interface generic, with type parameter(s), e.g.:
interface Filter<T1, T2> {
fun filter(t1: T1, t2: T2): Boolean
}
Then it's up to the implementation to specify which types are needed.  However, the calling code either needs to know the types of the particular implementation, or needs to be generic itself, or the interface needs to provide type bounds with in variance.
Or if you need a variable number of parameters, you could bundle them up into a single object and pass that.  However, you'd probably need an interface for that type, in order to handle the different numbers and types of parameters, and/or make that type a type parameter on Filter — all of which smells pretty bad.
Ultimately, I suspect you need to think about how your interface is going to be used, and in particular how its method is going to be called.  If you're only ever going to call it when the caller knows the implementation type, then there's probably no point trying to specify that method in the interface (and maybe no point having the interface at all).  Or if you'll want to handle Filter instances without knowing their concrete type, then look at how you'll want to make those calls.
The whole this is wrong!
First, OOP is a declarative concept, but in your example the type Filter is just a procedure wrapped in an object. And this is completely wrong.
Why do you need this type Filter? I assume you need to get a collection filtered, so why not create a new object that accepts an existing collection and represents it filtered.
class Filtered<T>(private val origin: Iterable<T>) : Iterable<T> {
override fun iterator(): Iterator<T> {
TODO("Filter the original iterable and return it")
}
}
Then in your code, anywhere you can pass an Iterable and you want it to be filtered, you simply wrap this original iterable (any List, Array or Collection) with the class Filtered like so
acceptCollection(Filtered(listOf(1, 2, 3, 4)))
You can also pass a second argument into the Filtered and call it, for example, predicate, which is a lambda that accepts an element of the iterable and returns Boolean.
class Filtered<T>(private val origin: Iterable<T>, private val predicate: (T) -> Boolean) : Iterable<T> {
override fun iterator(): Iterator<T> {
TODO("Filter the original iterable and return it")
}
}
Then use it like:
val oddOnly = Filtered(
listOf(1, 2, 3, 4),
{ it % 2 == 1 }
)

Get index of given element from array extension function kotlin

I'd like to understand Kotlin extension functions more and am trying to implement an extension function for a List, to get the index of an element by passing the value of the position (if that makes sense).
What I have:
fun List<String>.getItemPositionByName(item: String): Int {
this.forEachIndexed { index, it ->
if (it == item)
return index
}
return 0
}
Although this works fine, I would need the same thing for Int too.
To my question, is there a way of combining this into one extension function instead of two seperate ones? I acknowledge that this isn't a lot of code and wouldn't hurt to be duplicated but out of interest and for future references.
I'm aware of this question Extension functions for generic classes in Kotlin where the response is - as I understand it at least - "doesn't quite work like this, but I don't really need it for type but "just" for String and Int.
Kotlin supports what C++ people would refer to as specialization to a certain degree. It works just fine for very basic types like you're using so what you're asking of is definitely possible.
We can declare the following declarations. Of course you could just duplicate the code and you'd be on your way.
public fun List<String>.getItemPositionByName(item: String) = ...
public fun List<Int>.getItemPositionByName(item: String) = ...
If you're not a fan of repeating the code, the idiomatic way would be to make use of file-private functions and simply delegating to the private function.
private fun <T> getItemImpl(list: List<T>, item: T): Int {
list.forEachIndexed { index, it ->
if (it == item)
return index
}
return -1
}
public fun List<String>.getItemPositionByName(item: String) = getItemImpl(this, item)
public fun List<Int>.getItemPositionByName(item: Int) = getItemImpl(this, item)
This limits the getItemImpl which is fully generic to the current file you're in while the Int and String specializations are publicly available anywhere else.
Attempting to call getItemPositionByName on any list which is not of type List<Int> or List<String> will fail with a type error.
Kotlin Playground Link: https://pl.kotl.in/NvIRXwmpU
And just in case you weren't aware, the method you're implementing already exists in the standard library (https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/index-of.html)
The Kotlin standard library already has a function that does this: indexOf().
val one = listOf("a", "b", "c").indexOf("b")
check(one == 1)
One option is to look at the implementation of that function.
There is also the first() function, which you could use if you wanted write your own generic version:
fun <T> List<T>.getItemPositionByName(item: T) = withIndex()
.first { (_, value) -> item == value }
.index
fun main(args: Array<String>) {
val one = listOf("a", "b", "c").getItemPositionByName("b")
check(one == 1)
}
Or, rewriting your original version to use generics:
fun <T> List<T>.getItemPositionByName(item: T): Int {
this.forEachIndexed { index, it ->
if (it == item)
return index
}
return 0
}

Is Kotlin's mapIndexed guaranteed to retain ordering

mapIndexed on an array curiously returns a List not an array which isn't immediately intuitive.
I also noticed that kotlin.collections.mapIndexed documentation does not mention retention of ordering but kotlin.sequences.mapindexed does.
I know that since it's not explicit in the doc, I shouldn't rely on it, but wondering if it's an intentional omission.
I believe it is an omittion, it wouldn't be that practical to change the order of the elements, it would be highly unperformant.
The order is at least guaranteed by the implementation of the method as you can see below.
An enhanced for loop is used to loop through the whole collection and it applies the change only to the concerned index.
The fact that it returns a List is logical, since you'll get the same List back (actually a full copy - but with the same objects), only with the changes required.
/**
* Applies the given [transform] function to each element and its index in the original collection
* and appends the results to the given [destination].
* #param [transform] function that takes the index of an element and the element itself
* and returns the result of the transform applied to the element.
*/
public inline fun <T, R, C : MutableCollection<in R>> Iterable<T>.mapIndexedTo(destination: C, transform: (index: Int, T) -> R): C {
var index = 0
for (item in this)
destination.add(transform(checkIndexOverflow(index++), item))
return destination
}
Order is retained in the results.
Check out my code here - changing the first item in the list:
val convertedResults = mutableListOf<DisplayItem>()
myList.mapIndexedNotNullTo(convertedResults) { index, item ->
val member = DisplayItem(item)
if (member.id == "id_007") {
// add it first in the list
convertedResults.add(0, member)
null
} else
member
}
This works well. But I don't know how to measure the performance here. Tell me what do you think about this code.
An indication that the order is retained is also in /libraries/stdlib/test/collections/IterableTests.kt (link to latest revision in master at this time) of the official Kotlin repository
abstract class IterableTests<T : Iterable<String>>(val createFrom: (Array<out String>) -> T, val empty: T) {
fun createFrom(vararg items: String): T = createFrom(items)
val data = createFrom("foo", "bar")
[...]
#Test
fun mapIndexed() {
val shortened = data.mapIndexed { index, value -> value.substring(0..index) }
assertEquals(2, shortened.size)
assertEquals(listOf("f", "ba"), shortened)
}
So the test also assumes the same order for output. This is odd by the way as this code is not only used for testing List and others but also for testing an unordered Set.
Similar code is used for testing mapIndexed on arrays of all types.

BiMap / 2-way hashmap in Kotlin

is there a bidirectional hashmap for kotlin?
If not - what is the best way to express this in kotlin?
Including guava to get the BiMap from there feels like shooting with a very big gun on a very little target - no solution that I can imagine currently feels right - the best thing I have in mind is to write a custom class for it
I need a simple BiMap implementation too so decided to create a little library called bimap.
The implementation of BiMap is quite straightforward but it contains a tricky part, which is a set of entries, keys and values. I'll try to explain some details of the implementation but you can find the full implementation on GitHub.
First, we need to define interfaces for an immutable and a mutable BiMaps.
interface BiMap<K : Any, V : Any> : Map<K, V> {
override val values: Set<V>
val inverse: BiMap<V, K>
}
interface MutableBiMap<K : Any, V : Any> : BiMap<K, V>, MutableMap<K, V> {
override val values: MutableSet<V>
override val inverse: MutableBiMap<V, K>
fun forcePut(key: K, value: V): V?
}
Please, notice that BiMap.values returns a Set instead of a Collection. Also BiMap.put(K, V) throws an exception when the BiMap already contains a given value. If you want to replace pairs (K1, V1) and (K2, V2) with (K1, V2) you need to call forcePut(K, V). And finally you may get an inverse BiMap to access its keys by values.
The BiMap is implemented using two regular maps:
val direct: MutableMap<K, V>
val reverse: MutableMap<V, K>
The inverse BiMap can be created by just swapping the direct and the reverse maps. My implementation provides an invariant bimap.inverse.inverse === bimap but that's not necessary.
As mentioned earlier the forcePut(K, V) method can replace pairs (K1, V1) and (K2, V2) with (K1, V2). First it checks what the current value for K1 is and removes it from the reverse map. Then it finds a key for value V2 and removes it from the direct map. And then the method inserts the given pair to both maps. Here's how it looks in code.
override fun forcePut(key: K, value: V): V? {
val oldValue = direct.put(key, value)
oldValue?.let { reverse.remove(it) }
val oldKey = reverse.put(value, key)
oldKey?.let { direct.remove(it) }
return oldValue
}
Implementations of Map and MutableMap methods are quite simple so I will not provide details for them here. They just perform an operation on both maps.
The most complicated part is entries, keys and values. In my implementation I create a Set that delegates all method invocations to direct.entries and handle modification of entries. Every modification happens in a try/catch block so that the BiMap remains in consistent state when an exception is thrown. Moreover, iterators and mutable entries are wrapped in similar classes. Unfortunately, it makes iteration over entries much less efficient because an additional MutableMap.MutableEntry wrapper is created on every iteration step.
If speed is not a priority ( O(n) complexity ) you can create an extension function: map.getKey(value)
/**
* Returns the first key corresponding to the given [value], or `null`
* if such a value is not present in the map.
*/
fun <K, V> Map<K, V>.getKey(value: V) =
entries.firstOrNull { it.value == value }?.key
FWIW, you can get the inverse of the map in Kotlin using an extension function:
fun <K, V> Map<K, V>.inverseMap() = map { Pair(it.value, it.key) }.toMap()
The map operator can be used to iterate over the List of key-value pairs in the Map, then convert back to a map using .toMap().
Well, you are right - as it stated in a similar question for Java "Bi-directional Map in Java?", Kotlin does not have BiMap out of the box.
The workarounds include using Guava and creating a custom class using two usual maps:
class BiMap<K, V>() {
private keyValues = mutableMapOf<K, V>()
private valueKeys = mutableMapOf<V, K>()
operator fun get(key: K) = ...
operator fun get(value: V) = ...
...
}
This solution should not be slower or take more memory than a more sophisticated one. Although I am not sure what happens when K is the same as V.
The cleanest solution to to use Guava and create an extension function that turns a Map into a BiMap. This follows the semantics of Kotlin's other Map conversions as well. Although Guava might have a bit of overhead, you gain the flexibility to add more extension functions wrappers in the future. You can always remove Guava in the future and replace the extension function with another implementation.
First declare your extension function.
fun <K, V> Map<K, V>.toBiMap() = HashBiMap.create(this)
Then use it like this:
mutableMapOf("foo" to "bar", "me" to "you").toBiMap()