When representing a width-height combo, is there a...
# android
m
When representing a width-height combo, is there any advantage (other than interactions with other code requiring
Point
) to using
Point
instead of
Pair<Int, Int>
? I’m preferring
Pair
(because of destructuring and also not being Android-specific) but since I’m creating potentially tens of thousands of these objects, I wanted to check if there is any performance issues.
h
Point is Parcelable and Pair is serializable, Serializable uses reflection and is not as efficient as Parcelable so it really depends on your use case
👍 1
m
For
Pair<Int, Int>
does the compiler optimise to use two primitive `int`s or two
Integer
objects?
k
The only real advantage for using explicit user defined type such as Point instead of Pair is that you can provide explicit names for the properties of user defined types and use those properties without having to destructure the type. Besides, from code readability perspective, it becomes clear what that structure represents. For example, if I see Point class in codebase it immediately clicks that it represents x,y points in 2D space. By the way width-height combo should be represented using Dimension data class not Point.
h
from what i understand non nullable Int is same as primitive int in java but the nullable int is a boxed object
👍 1
and I am not sure If there is any under the hood optimization is there for Int but Pair is just kind of a container right, It will just hold two reference or values in case of primitives
m
Do you mean Anko’s
Dimension
or Android’s
Dimension
annotation? Surely only applicable to UI width/height not generic width/height.
k
Dimension is for generic width/height. it is not android specific.
Shapes in 2D space has dimensions of width and height. Unless you want to use width and height to represent something that does not exist in 2D space.
m
Sure, but the only
Dimension
classes I can see are an annotation class in Android and a data class in Anko.
k
Infact, the Dimension annotation in android is more of a naming misnormer considering its usage which just represents units of measurement. It was supposed to be named something like Unit which is what Jetpack compose did if not mistaken. Besides, naming your data class Dimension would not conflict with the existing annotation. Just like Android, it reuses much of the java API libraries underneath and defines its own API that has classes with similar names as java API. The only differentiator is the package name. In conclusion, it is perfectly fine to name a class with a name already existing in the framework as long as you use a unique package name.
m
Yes of course. It’s just I thought you were referring to an existing class rather than creating a new one.
t
Pair<A, B>
is a class with 2 generic parameters. Due to type erasure on the JVM, this class is compiled as
Pair
with two fields of type
Any
. So there is no compiler optimization for it :
Pair<Int, Int>
uses boxed ints (
Integer
). If you use a lot of them, I suggest that you define your own class, it's only one line :
Copy code
data class Dimension(val width: Int, val height: Int)
👍 1
c
Pair is more expensive, due to autoboxing. Note that on Android, the cost of autoboxing is reduced for small ints, since there's a fixed lookup table of constants, so something to be aware of while measuring. You can verify the cost pretty easily with a benchmark on Android using d.android.com/benchmark
Copy code
@get:Rule
    val benchmarkRule = BenchmarkRule()

    @Test
    fun pair() = benchmarkRule.measureRepeated {
        Pair(10000, 20000)
    }

    @Test
    fun point() = benchmarkRule.measureRepeated {
        Point(10000, 20000)
    }
Results on Pixel1, running Q:
Copy code
benchmark:           222 ns ExampleBenchmark.pair
benchmark:            48 ns ExampleBenchmark.point
👍 1
but Pair is just kind of a container right, It will just hold two reference or values in case of primitives
Kotlin pair doesn't have any such optimizations in the compiler - it's always references.
g
Adding to what @Klaas Kabini said here
By the way width-height combo should be represented using Dimension data class not Point.
I believe the width+height combo would be represented by
Rect
.
Point
is a single coordinate, and
Rect
is pair of coordinates, thus you'd get width and height
@Mark, I think you could extend
Point
and
Rect
with
componentN
and get destructuring declarations without the cost of autoboxing: https://kotlinlang.org/docs/reference/multi-declarations.html#example-destructuring-declarations-and-maps
m
Thanks @Gabriel Feo but I think creating your own
data class Dimension(val width: Int, val height: Int)
is the way to go.
g
Certainly your property names are clearer than `Rect`'s 😅