Pre-initialize size of List/Collection/etc [duplicate] - kotlin

I'm creating a list of values, in a context where it so happens that, though the values are being added one at a time, the eventual number is known in advance. This is in a function that will be called many times, so the faster it runs, the better.
In Java, I would use the ArrayList constructor that specifies an initial capacity, because in theory this makes it slightly faster because it avoids resizing.
In Kotlin, one normally uses mutableListOf(), but this does not allow an initial capacity; in theory this should result in slightly slower code.
Is the recommended/idiomatic Kotlin solution in this case:
Go ahead and use the ArrayList constructor; ArrayList is a perfectly valid MutableList.
Ignore the issue; the initial capacity never actually makes a measurable difference to speed.
Something else?

Fill an immutable list
val doubles = List(5) { i -> i * 2 }
result --> [0, 2, 4, 6, 8]
Fill a mutable list of five elements with zeros
val ints = MutableList(5) { 0 }
result --> [0, 0, 0, 0, 0]

Updated Answer
I was actually confused with capacity and size. There is no implementation of using a default capacity MutableList currently in Kotlin stdlib.
You can make one yourself.
fun <T> mutableListWithCapacity(capacity: Int): MutableList<T> =
ArrayList(capacity)
// creates a MutableList of Int with capacity of 5.
val mutableList = mutableListWithCapacity<Int>(5)
Outdated Answer
One of the reason why mutableListOf does not allow for default capacity is because default values in kotlin is not null.
However there is a utility function defined in kotlin.collections package.
public inline fun <T> MutableList(size: Int, init: (index: Int) -> T): MutableList<T> {
val list = ArrayList<T>(size)
repeat(size) { index -> list.add(init(index)) }
return list
}
You can create a List with a List function or MutableList function with a default capacity and its mapping.
// creates a list of ints with default capacity of 10 and having nulls.
// But I highly doubt you should initialize it with a null since Kotlin is a null-safe language.
val list = MutableList<Int?>(10) { null }
But since there should not be nulls in Kotlin if it is intended use of non-null list else you have to do a null check using operators like ?. !!..

You can wrap this mutableList() predefined function in a function like the following
fun <E> emptyMutableList(size: Int = 0): MutableList<E?> {
return MutableList(size) {
null
}
}
this will return a MutableList of size size but also with null assigned to all of its cells. Now if you want to access any index value, your program will not crash with java.lang.IndexOutOfBoundsException like it would if you use the solution in the accepted answer. Here is what I mean:
fun <E> emptyMutableList(size: Int = 0): MutableList<E?> {
return MutableList(size) {
null
}
}
fun <T> mutableListWithCapacity(capacity: Int): MutableList<T> =
ArrayList(capacity)
fun main() {
val mutableList1 = mutableListWithCapacity<Int>(20)
val mutableList2 = emptyMutableList<Int>(20)
mutableList1[10] // this will throw a java.lang.IndexOutOfBoundsException
mutableList2[10] // this will not throw an exception but it will return null
}
Of course everything depends on how memory efficient vs crash-free you want your program to be.
Happy coding!

Related

Is it possible to implement sequence programming with vararg in Kotlin?

I've been trying sequence programming for processing the data I get from the vararg argument. I want to multiply every number in the list and add it to the new array list. Is it possible to use sequences.
I attach the code below:
fun main() {
val number = asList(10, 20, 30, 40, 50)
print(number)
}
fun <T> asList(vararg input: T): List<T> {
val result = ArrayList<T>()
input.map {it * 2}.foreach(result.add(it))
return result
}
Here is the error I get:
enter image description here
Yes, it's possible to create a sequence from a vararg; I'll come back to that later.
First, the main problem in the code above is that, unfortunately, it can't be done generically.  The error you're getting is because T could be any type, and most types can't be multiplied, so the compiler is telling you that you can't do the * 2.
You might think of restricting T to subclasses of Number, but that doesn't help.  (Number is a very weak type; it doesn't let you do any arithmetic, probably because you can't tell what type the result would have to be, nor what rounding or overflow might occur.  All it lets you do is convert the value to specific types.)
But if you remove the type parameter and code it for a particular numeric type, such as Int, then it can work fine.
There are also spelling and syntax errors in the code around the foreach call.  Fixing those too gives e.g.:
fun asList(vararg input: Int): List<Int> {
val result = ArrayList<Int>()
input.map{ it * 2 }.forEach{ result.add(it) }
return result
}
That's doing a lot of unnecessary work, though; the map() already returns a list, so there's no point in creating a second list and copying to it element-by-element!  Also, the name is misleading.  So it could just be:
fun asListDoubled(vararg input: Int) = input.map{ it * 2 }
Your question mentioned sequences; but your code uses normal eager lists.  If you want a lazily-evaluated sequence, you can just add an asSequence() call, e.g.:
fun asSequenceDoubled(vararg input: Int) = input.asSequence().map{ it * 2 }
But note that this now returns a Sequence<Int>, not List<Int>, so you can go on and do further lazy operations on it.  (If you want a List<Int>, then you can just append a toList() call — but there's little point in using a sequence only for the doubling, as the sequence overhead is probably far higher than any saving.)

Kotlin Generics - It is possible get integer position of an element of whatever type passed like ordinals method does for Enum defined classes?

There's an already built in way that fulfill my request?
I know Set are unordered
I need to do a vector based Set.
I need to know the position of any value of a generic type to place them in the corresponding index of the array, So I can avoid duplications of the elements.
I'm not ordering or defining an order of the Set.
I don't have any operators that missbehave or break any Set Costraint
Please note that I know this implementation is not efficient for any types that seems infinite like Integers.
I need to do it for an educational purpose.
I have already implemented List Ordered and Hash Table based ones.
For now I have this class, that works flawlessy:
package ads
class MySet<E : Enum<E>> {
//More details for clarify
private val maxSet = 127
private var myset = arrayOfNulls<Boolean>(maxSet)
private fun getOrdinal(eelement : E) : Int{
return eelement.ordinal
}
/*
more set operators that needs of getOrdinal
*/
fun insert(xelement: E){
myset[getOrdinal(xelement)] = true
}
}
import ads.MySet as RawSet
enum class MyColors{
Red,
Green,
Blue,
Yellow,
Black,
Mint;
}
fun main() {
val myfavc = RawSet<MyColors>()
val yourfavc = RawSet<MyColors>()
//Following operations...
myfavc.insert(MyColors.Red)
yourfavc.insert(MyColors.Blue)
}
I need now to make another class in the same way but working with whatever abstract type already defined in kotlin.
package ads
class MySet<T> {
//More details for clarify
private val maxSet = 127
private var myset = arrayOfNulls<Boolean>(maxSet)
private fun getOrdinal(telement : T) : Int{
/*
For any abstract type return the order of any element
checks if the integer is not greater than maxSet otherwhise it
throws an Exception or manages this istance in other way
*/
}
/*
more set operators that needs of getOrdinal
*/
fun insert(xelement: T){
myset[getOrdinal(xelement)] = true
}
}
import ads.MySet as RawSeT
//Istance using Int
fun main() {
val myfav = RawSet<Int>()
val yourfav = RawSet<Int>()
//Following operations...
myfav.insert(11)
yourfav.insert(123)
}
I guess there's no built-in way to do so in a generic way.
but I'm still learning kotlin, so maybe I'm missing something useful.
I'm not asking to do my paper.
I don't need a full alternative solutions that I should find out by myself but
I'm opened to read about any tips or resources that can help me to clarify how abstract types works in Kotlin(or Programming Languages) infos like :
How are ordered.
If any value of any type can be compared based on their position
(like c > a for chars).
Range of values/Max values represented for any "apparently
infinite" type like Integers.
Thanks you!
P.S. = Please consider that I'm not an english native, be patient!
Enums are implicitly ordered in declaration order and amount of instances of each enum is finite, so they could be ordered globally and their ordinal could be represented as Int.
Ints (as well as Bytes and Chars) are naturally ordered and have ranges (Int.MIN_VALUE..Int.MAX_VALUE, etc.), so each of them could have an ordinal represented as Int too.
All types implementing Comparable interface could be compared in pairs and any subset of their instances could be ordered, but it doesn't mean that each of them have some global Int ordinal among all possible instances, because set of Ints is finite (2^32 items), and set of all unique instances of generic type T could be countably infinite (like BigInteger) or even uncountable (like Double) (see wiki about cardinality).
All other types couldn't be even compared in pairs (without respectful Comparator<T>).
So you need to manually limit instances of each T that are about to be added in your set and either maually order them or provide respectful Comparator<T> to construct a Map<T, Int> which you'll need to use for subsequent ordinal evaluation:
class SetOfSomehowOrderedInstancesOfType<T>(private val order: Map<T, Int>) {
private val maxSet = order.size
private var myset = BooleanArray(order.size)
private fun getOrdinal(eelement: T): Int {
return order[eelement] ?: throw RuntimeException("Order unknown")
}
fun insert(xelement: T) {
myset[getOrdinal(xelement)] = true
}
}
Usage:
fun main() {
val myFavouriteRealNumbersInMyFavouriteOrder =
listOf(99.2123, -2355.12, 1.1, 3.14, 100.0, 123214214215.123331322145)
val myfavc = SetOfSomehowOrderedInstancesOfType<Double>(myFavouriteRealNumbersInMyFavouriteOrder.mapToIndex())
myfavc.insert(99.2123) //will be inserted with ordinal = 0
val myFavouriteRealNumbersInNaturalOrder = myFavouriteRealNumbersInMyFavouriteOrder.sorted()
val yourfavc = SetOfSomehowOrderedInstancesOfType<Double>(myFavouriteRealNumbersInNaturalOrder.mapToIndex())
yourfavc.insert(99.2123) //will be inserted with ordinal = 3
}
Alternatively you may define Orderable and Ordinator<T> interfaces (similar to Comparable<T> and Comparator<T>) and determine ordinal using them:
fun interface Ordinator<T> {
fun getOrderOf(x : T) : Int
}
interface Orderable {
val order : Int
}
class MySet<T>(private val ordinator: Ordinator<T>? = null) {
private val maxSet = 127
private var myset = BooleanArray(maxSet)
private fun getOrdinal(eelement: T) = when {
eelement is Orderable -> eelement.order
ordinator != null -> ordinator.getOrderOf(eelement)
else -> throw RuntimeException()
}
fun insert(xelement: T) {
myset[getOrdinal(xelement)] = true
}
}
Also you may define auxilary function, generalizing previous approach:
fun <T> ordinatorOf(order: List<T>) = object : Ordinator<T> {
private val order = order.mapToIndex()
override fun getOrderOf(x: T) = this.order[x] ?: throw RuntimeException()
}
Usage:
val stringsOrderedByTheirLength = MySet<String> { it.length }
stringsOrderedByTheirLength.insert("aaa") //will be inserted with ordinal = 3
val myFavouriteRealNumbersInMyFavouriteOrder =
listOf(99.2123, -2355.12, 1.1, 3.14, 100.0, 123214214215.123331322145)
val myfavc = MySet(ordinatorOf(myFavouriteRealNumbersInMyFavouriteOrder))
myfavc.insert(99.2123) //will be inserted with ordinal = 0
As somebody pointed out to me that some abstract types representing for an istance Real Numbers can't be done so easily.
The implementation with the enum class works flawlessy but it's been refused from my university professor because I need to use the same syntax for every implementation of the same Data Structure.
Other implementation I have
- HashTableSet<T>
- OrderedListSet<T>
they ask only for an abstract type that can be whatever type, they will work without problem.
I need to do it the same with the
ArraySet<E : Enum<E>>
So if this can't be done easily with Generics, directly...
I'm thinking about mixing them.
Like whatever T type I have
it creates an object called "Domain" so whatever element it insert, before placing them in the array of the set, it place them inside there in a specific order so it simulates what enum it was doing.
I guess that Enumerations can't be defined during the runtime, dinamically.
Then probably I have to define Domain<T> as a private class/object(not sure) that :
Collect the element of the istance of ArraySet(above MySet) inserts with its opeator .insert()
It orders the element comparing to the ones that are already inside
Once is ordered delete all the duples
Re-arrange the whole Boolean Array everytime insert is used based on how Domain grows. (or find out a different algo that partially re-arrange the boolean array)
What do you think?
Advice me more, thanks.

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
}

Kotlin MutableList initial capacity

I'm creating a list of values, in a context where it so happens that, though the values are being added one at a time, the eventual number is known in advance. This is in a function that will be called many times, so the faster it runs, the better.
In Java, I would use the ArrayList constructor that specifies an initial capacity, because in theory this makes it slightly faster because it avoids resizing.
In Kotlin, one normally uses mutableListOf(), but this does not allow an initial capacity; in theory this should result in slightly slower code.
Is the recommended/idiomatic Kotlin solution in this case:
Go ahead and use the ArrayList constructor; ArrayList is a perfectly valid MutableList.
Ignore the issue; the initial capacity never actually makes a measurable difference to speed.
Something else?
Fill an immutable list
val doubles = List(5) { i -> i * 2 }
result --> [0, 2, 4, 6, 8]
Fill a mutable list of five elements with zeros
val ints = MutableList(5) { 0 }
result --> [0, 0, 0, 0, 0]
Updated Answer
I was actually confused with capacity and size. There is no implementation of using a default capacity MutableList currently in Kotlin stdlib.
You can make one yourself.
fun <T> mutableListWithCapacity(capacity: Int): MutableList<T> =
ArrayList(capacity)
// creates a MutableList of Int with capacity of 5.
val mutableList = mutableListWithCapacity<Int>(5)
Outdated Answer
One of the reason why mutableListOf does not allow for default capacity is because default values in kotlin is not null.
However there is a utility function defined in kotlin.collections package.
public inline fun <T> MutableList(size: Int, init: (index: Int) -> T): MutableList<T> {
val list = ArrayList<T>(size)
repeat(size) { index -> list.add(init(index)) }
return list
}
You can create a List with a List function or MutableList function with a default capacity and its mapping.
// creates a list of ints with default capacity of 10 and having nulls.
// But I highly doubt you should initialize it with a null since Kotlin is a null-safe language.
val list = MutableList<Int?>(10) { null }
But since there should not be nulls in Kotlin if it is intended use of non-null list else you have to do a null check using operators like ?. !!..
You can wrap this mutableList() predefined function in a function like the following
fun <E> emptyMutableList(size: Int = 0): MutableList<E?> {
return MutableList(size) {
null
}
}
this will return a MutableList of size size but also with null assigned to all of its cells. Now if you want to access any index value, your program will not crash with java.lang.IndexOutOfBoundsException like it would if you use the solution in the accepted answer. Here is what I mean:
fun <E> emptyMutableList(size: Int = 0): MutableList<E?> {
return MutableList(size) {
null
}
}
fun <T> mutableListWithCapacity(capacity: Int): MutableList<T> =
ArrayList(capacity)
fun main() {
val mutableList1 = mutableListWithCapacity<Int>(20)
val mutableList2 = emptyMutableList<Int>(20)
mutableList1[10] // this will throw a java.lang.IndexOutOfBoundsException
mutableList2[10] // this will not throw an exception but it will return null
}
Of course everything depends on how memory efficient vs crash-free you want your program to be.
Happy coding!

In Kotlin, how do I idiomatically access nullable nested map values, or return a default?

Quick Kotlin best practices question, as I couldn't really work out the best way to do this from the documentation.
Assume I have the following nested map (typing specified explicitly for the purpose of this question):
val userWidgetCount: Map<String, Map<String, Int>> = mapOf(
"rikbrown" to mapOf(
"widgetTypeA" to 1,
"widgetTypeB" to 2))
Can the following mode be any more succinct?
fun getUserWidgetCount(username: String, widgetType: String): Int {
return userWidgetCount[username]?.get(widgetType)?:0
}
In other words, I want to return the user widget count iff the user is known and they have an entry for that widget type, otherwise zero. In particular I saw I can use [] syntax to access the map initially, but I couldn't see a way to do this at the second level after using ?..
I would use an extension operator method for that.
// Option 1
operator fun <K, V> Map<K, V>?.get(key: K) = this?.get(key)
// Option 2
operator fun <K, K2, V> Map<K, Map<K2, V>>.get(key1: K, key2: K2): V? = get(key1)?.get(key2)
Option 1:
Define an extension that provides get operator for nullable map. In Kotlin's stdlib such approach appears with Any?.toString() extension method.
fun getUserWidgetCount(username: String, widgetType: String): Int {
return userWidgetCount[username][widgetType] ?: 0
}
Option 2:
Create a special extension for map of maps. In my opinion, it is better because it shows the contract of the map of maps better than two gets in a row.
fun getUserWidgetCount(username: String, widgetType: String): Int {
return userWidgetCount[username, widgetType] ?: 0
}