trevjones
11/21/2019, 6:05 PMa.mapIndexed { index, value -> value to myList[index] }.toMap()
?Hullaballoonatic
11/21/2019, 6:05 PMtrevjones
11/21/2019, 6:06 PMHullaballoonatic
11/21/2019, 6:06 PMa.zip(b)
trevjones
11/21/2019, 6:08 PMHullaballoonatic
11/21/2019, 6:08 PMkarelpeeters
11/21/2019, 7:28 PMa.withIndex().associateBy({ (_, v) -> v }, { (i, _) -> b[i] })
looks terrible but doesn't have any overhead.trevjones
11/21/2019, 7:38 PMinline fun <K, V> Iterable<K>.associateByIndex(valueSelector: (index: Int) -> V): Map<K, V> {
return withIndex().associateBy({ (_, k) -> k}, { (i, _) -> valueSelector(i) })
}
val a = listOf(1,2,3)
val b = listOf("one", "two", "three")
val c = a.associateByIndex { b[it] }
println(c.toString())
karelpeeters
11/21/2019, 7:39 PMassociateWith
, no? Also, are you sure crossinline
is necessary? It kind of defeats the purpose of inline
.trevjones
11/21/2019, 8:02 PMtrevjones
11/21/2019, 8:12 PM2N+3
where N is the size of the IterableReceiver assuming the valueSelector doesn't allocateHullaballoonatic
11/21/2019, 8:47 PMassociateWithIndexed
according to stdlib naming convention if including the indices in the params of the transformArkady Bazhanov
11/21/2019, 8:47 PMfun <K, V> Iterable<K>.associateWith(values: Iterable<V>): Map<K, V> {
return values.iterator().run {
associateWith { next() }
}
}
Hullaballoonatic
11/21/2019, 8:47 PMwithIndex
had overhead...trevjones
11/21/2019, 8:48 PMArkady Bazhanov
11/21/2019, 8:51 PMkarelpeeters
11/21/2019, 9:01 PMkarelpeeters
11/21/2019, 9:43 PMBenchmark Mode Cnt Score Error Units
MapBenchmarks.iterator thrpt 10 5095.020 ± 105.089 ops/s
MapBenchmarks.manualAlloc thrpt 10 4190.481 ± 209.660 ops/s
MapBenchmarks.manual thrpt 10 2686.919 ± 60.247 ops/s
MapBenchmarks.mapIndexed thrpt 10 3820.297 ± 34.474 ops/s
MapBenchmarks.sequenceZip thrpt 10 2415.201 ± 60.417 ops/s
MapBenchmarks.withIndexAssociate thrpt 10 2360.287 ± 43.676 ops/s
MapBenchmarks.withIndexAssociateByTo thrpt 10 2311.393 ± 19.049 ops/s
MapBenchmarks.zip thrpt 10 4021.002 ± 127.191 ops/s
I can't really think of a reason why manualAlloc
is slower than iterator
, but I've spent too much time on this already 🙂Hullaballoonatic
11/21/2019, 10:36 PMHullaballoonatic
11/21/2019, 10:37 PMHullaballoonatic
11/21/2019, 10:37 PMkarelpeeters
11/21/2019, 10:38 PMHullaballoonatic
11/21/2019, 10:41 PMHullaballoonatic
11/21/2019, 10:41 PMtrevjones
11/21/2019, 10:41 PMkarelpeeters
11/21/2019, 10:44 PMMap.put
for each element.Hullaballoonatic
11/21/2019, 10:44 PMkarelpeeters
11/21/2019, 10:45 PMHullaballoonatic
11/21/2019, 10:45 PMHullaballoonatic
11/21/2019, 10:48 PMHullaballoonatic
11/21/2019, 10:48 PMHullaballoonatic
11/21/2019, 10:49 PMHullaballoonatic
11/21/2019, 10:49 PMkarelpeeters
11/21/2019, 10:49 PMfor (i in listA.indiches)
gets to compiled to a java-style int size = listA.size; for(int i = 0; i < size; i++)
so that should be fine.karelpeeters
11/21/2019, 10:50 PMkarelpeeters
11/21/2019, 10:50 PMtrevjones
11/21/2019, 10:50 PMList(10_000) { Random.nextInt() }
ends up backed by ArrayList so those lookups should be O(1) cheap. my thinking is JVM impl is crazy good with iterators?Hullaballoonatic
11/21/2019, 10:50 PMtrevjones
11/21/2019, 10:50 PMtrevjones
11/21/2019, 10:51 PMkarelpeeters
11/21/2019, 10:51 PMmanualAlloc
preallocates the right size.karelpeeters
11/21/2019, 10:52 PMHullaballoonatic
11/21/2019, 10:52 PMtrevjones
11/21/2019, 10:52 PMkarelpeeters
11/21/2019, 11:15 PMMapBenchmarks.iterator thrpt 10 6338.874 � 1001.794 ops/s
MapBenchmarks.manual thrpt 10 6469.501 � 79.655 ops/s
MapBenchmarks.manualAlloc thrpt 10 7929.022 � 107.842 ops/s
MapBenchmarks.mapIndexed thrpt 10 4913.874 � 63.817 ops/s
MapBenchmarks.sequenceZip thrpt 10 5423.528 � 329.522 ops/s
MapBenchmarks.withIndexAssociate thrpt 10 5299.546 � 98.017 ops/s
MapBenchmarks.withIndexAssociateByTo thrpt 10 4802.971 � 98.678 ops/s
MapBenchmarks.zip thrpt 10 4801.796 � 337.945 ops/s
Random numbers again:
MapBenchmarks.iterator thrpt 10 5128.317 � 151.363 ops/s
MapBenchmarks.manual thrpt 10 2673.094 � 27.443 ops/s
MapBenchmarks.manualAlloc thrpt 10 5484.122 � 123.091 ops/s
MapBenchmarks.mapIndexed thrpt 10 3889.280 � 38.294 ops/s
MapBenchmarks.sequenceZip thrpt 10 2499.712 � 24.050 ops/s
MapBenchmarks.withIndexAssociate thrpt 10 2383.809 � 26.758 ops/s
MapBenchmarks.withIndexAssociateByTo thrpt 10 2353.679 � 62.273 ops/s
MapBenchmarks.zip thrpt 10 4128.566 � 105.939 ops/s
Now manualAlloc
is beating everything as I would expect... Typical benchmarking 🙂ilya.gorbunov
11/22/2019, 2:55 AMiterator
and manualAlloc
can be in the capacity of the map: manualAlloc
uses the exact collection size, and associateWith
(in iterator
) takes in account the default map fill factor of 0.75, so it uses the capacity equal to 4/3 times of the size.ilya.gorbunov
11/22/2019, 2:59 AMassocateWith
has been already taken by the overload with value selector.
https://youtrack.jetbrains.com/issue/KT-21587karelpeeters
11/22/2019, 1:35 PM