I want to fully understand the different between compareTo and equals.
I have used this code while trying to understand the difference between them:
println("${'A'.compareTo('b')}")
println("${'A'.equals('b')}")
While using compareTo I get -1 as a result. Nothing is wrong here.
It is also mentioned in the documentation that I will get -1 as a result if the strings are not the same:
Compares this object with the specified object for order. Returns zero if this object is equal to the specified other object, a negative number if it's less than other, or a positive number if it's greater than other.
And while using equals the result that I got was false, then again it looks good as the documentation mentioned - this method will return a boolean:
Indicates whether some other object is "equal to" this one.
Maybe I am missing something really simple, but in the described case, what is the difference between those methods (other than the value that is coming from compareTo and equals)?
The difference between equals and compareTo comes from a few sources.
First, equals is inherited from the Any type in Kotlin, so it is a method attached to all values in the language.
compareTo is inherited from the Comparable type, specifically meaning only its inheritors of:
Boolean, Byte, Char, Double, Duration, Enum, Float, Int etc...
will have the method.
Second, the signature of returned value is different.
Equals has a return of Boolean, meaning you only have true or false being returned from the method call. This will only tell you directly if they are the same or not, with no extra information
The compareTo method has a return of Int, which is a magnitude of the difference between the comparison of the input type. The comparison can not be between different types.
The return of a positive Integer that the Receiver value, is greater than the input value being checked against
To clarify, the Receiver is the variable or instance that the compareTo method is being called on.
For example:
val myValue: Boolean = false
val myCheck: Boolean = true
myValue.compareTo(myCheck) // Return: 1
In that code, the Receiver would be myValue because it is calling the method compareTo. Kotlin interprets true to be a greater value than false so myValue.compareTo(myCheck) will return1`
The return of 0 means that the Receiver value is the same value as the input parameter value.
val myValue: Boolean = true
val otherValue: Boolean = true
myValue.compareTo(otherValue) // Return: 0
The return of a negative number is a magnitude of difference between the two values, specific to each type based on the Receiver value being considered a value of less than the input parameter.
val myString = "zza"
val otherString = "zzz"
myString.compareTo(otherString) // Return: -25
The equality being a bit complicated to explain, but being the same length with only 1 Char place being different, it returns the difference of the Char values as an Int.
val myString = "zz"
val otherString = "zzz"
myString.compareTo(otherString) // Return: -1
In this case the difference is literally the existence of 1 Char, and does not have a value difference to assign.
For equals, the comparative other can be of Any type, not specifically the same type as the Receiver like in compareTo.
The equals method is also an operator function and can be syntactically used such as:
val myString: String = "Hello World"
val otherString: String = "Hello World"
myString == otherString // Return: true
Any non-null value can not be equal to null:
val myString = "Hello World"
val maybeNull: String? = null
myString == maybeNull // Return: false
Equality is specific to each type and has it's own specific documentation to clarify its nuances: Kotlin Equality
Related
I can't figure out what ?: does in for example this case
val list = mutableList ?: mutableListOf()
and why can it be modified to this
val list = if (mutableList != null) mutableList else mutableListOf()
TL;DR: If the resulting object reference [first operand] is not null, it is returned. Otherwise the value of the second operand (which may be null) is returned. Additionally, the operator can throw an exception if null is returned.
The Elvis operator is part of many programming languages, e.g. Kotlin but also Groovy or C#.
I find the Wikipedia definition pretty accurate:
In certain computer programming languages, the Elvis operator ?: is a binary operator that returns its first operand if that operand is true, and otherwise evaluates and returns its second operand. It is a variant of the ternary conditional operator, ? :, found in those languages (and many others): the Elvis operator is the ternary operator with its second operand omitted.
The following is especially true for Kotlin:
Some computer programming languages have different semantics for this operator. Instead of the first operand having to result in a boolean, it must result in an object reference. If the resulting object reference is not null, it is returned. Otherwise the value of the second operand (which may be null) is returned. If the second operand is null, the operator is also able to throw an exception.
An example:
x ?: y // yields `x` if `x` is not null, `y` otherwise.
x ?: throw SomeException() // yields `x` if `x` is not null, throws SomeException otherwise
The Elvis Operator is represented by a question mark followed by a colon: ?: and it can be used with this syntax:
first operand ?: second operand
It enables you to write a consise code, and works as such:
If first operand isn't null, then it will be returned. If it is null, then the second operand will be returned. This can be used to guarantee that an expression won't return a null value, as you'll provide a non-nullable value if the provided value is null.
For example(in Kotlin):
fun retrieveString(): String { //Notice that this type isn't nullable
val nullableVariable: String? = getPotentialNull() //This variable may be null
return nullableVariable ?: "Secondary Not-Null String"
}
In this case, if the computed value of getPotentialNull is not null, it will be returned by retrieveString; If it is null, the second expression "Secondary Not-Null String" will be returned instead.
Also note that the right-hand side expression is evaluated only if the left-hand side is null.
In Kotlin, you could use any expression as second operand, such as a throw Exception expression
return nullVariable ?: throw IllegalResponseException("My inner function returned null! Oh no!")
The name Elvis Operator comes from the famous American singer Elvis Presley. His hairstyle resembles a Question Mark
Source: Wojda, I. Moskala, M. Android Development with Kotlin. 2017. Packt Publishing
This is called the Elvis operator and it does... Exactly what you've described in your question. If its left hand side is a null value, it returns the right side instead, sort of as a fallback. Otherwise it just returns the value on the left hand side.
a ?: b is just shorthand for if (a != null) a else b.
Some more examples with types:
val x: String? = "foo"
val y: String = x ?: "bar" // "foo", because x was non-null
val a: String? = null
val b: String = a ?: "bar" // "bar", because a was null
Let's take a look at the defintion:
When we have a nullable reference r, we can say "if r is not null, use
it, otherwise use some non-null value x":
The ?: (Elvis) operator avoids verbosity and makes your code really concise.
For example, a lot of collection extension functions return null as fallback.
listOf(1, 2, 3).firstOrNull { it == 4 } ?: throw IllegalStateException("Ups")
?: gives you a way to handle the fallback case elgantely even if you have multiple layers of fallback. If so, you can simply chain multiply Elvis operators, like here:
val l = listOf(1, 2, 3)
val x = l.firstOrNull { it == 4 } ?: l.firstOrNull { it == 5 } ?: throw IllegalStateException("Ups")
If you would express the same with if else it would be a lot more code which is harder to read.
The elvis operator in Kotlin is used for null safety.
x = a ?: b
In the above code, x will be assigned the value of a if a is not null and b if a is null.
The equivalent kotlin code without using the elvis operator is below:
x = if(a == null) b else a
Simply we can say that, you have two hands. You want to know, is your left hand working right now?. If left hand not working, return empty else busy
Example for Java:
private int a;
if(a != null){
println("a is not null, Value is: "+a)
}
else{
println("a is null")
}
Example for Kotlin:
val a : Int = 5
val l : Int = if (a != null) a.length else "a is null"
Consider below example,
var myStr:String? = null
//trying to find out length of myStr, but it could be null, so a null check can be put as,
val len = if (myStr != null){
myStr.length
}
else{
-1
}
Using the elvis operator, the above code can be written in a single line
val len = myStr?.length ?: -1 // will return -1 if myStr is null else will return length
In addition to what has been already stated there is one good pattern that was not obvious for me, but which is common, e.g. you're writing a long function, but if something is null there is no sense to continue and the only thing you can do is to return from the function. Normally you'd write
something = expression
if (something == null) {
return
}
With elvis it becomes shorter and more elegant:
something = expression ?: return
Basically, if the left side of Elvis returns null for some reason, returns the right side instead.
i.e.
val number: Int? = null
println(number ?: "Number is null")
So, if number is NOT null, it will print number, otherwise will print "Number is null".
A little addition though is this
X = A ?: B
X will still be null if both A and B evaluate to null
Therefore, if you want X to always be non-null, make sure B is always a non-null or that B always evaluates to non-null if it's a function or expression.
I am currently trying to make a comparable object and working on the compareTo() function, for which I wrote the following code
class InfoAcad(e: String, m: String, c: Int): Comparable<InfoAcad> {
override operator fun compareTo(other: InfoAcad): Int {
if (this.e < other.e) return -1
if (this.e > other.e) return 1
if (this.e == other.e && this.m < other.m) return -1
if (this.e == other.e && this.m > other.m) return 1
return 0
}
}
The idea is that e is an ID number inputted as a string, which always follows the format XX-XXX where every X character is an integer between 0 and 9, and m is a course code following the format LL-XXX where each L character is a capital letter between A and Z and the X characters are integers between 0 and 9 like in the ID numbers. The objects are first compared by their ID number, and if the ID numbers are equal they are then compared by the course code, if both values are the same then the objects are equal, the c parameter is not taken into account in the comparison. I found out yesterday that I could compare strings directly in Kotlin in < and > relations, so I decided to try using that to make the task of comparing the InfoAcad objects a bit easier on myself, however when I make a main function to test the comparisons, the equality always returns a false value independently of what is in the string values of the InfoAcad objects. Here's said main function:
fun main() {
var A = InfoAcad("18-10125", "CI-2526", 3)
var B = InfoAcad("18-10125", "CI-2526", 5)
println("A = B: " + (A == B).toString()) //true
println("A < B: " + (A < B).toString()) //false
ptintln("A > B: " + (A > B).toString()) //false
}
When I change characters in the ID and course code values the inequality relations work just as intended, so what could be causing the equality relation to always return false? I appreciate and thank any responses in advance.
Note: I have also tried giving A and B the same c value, the equality part still returned false.
Override the equals function as well, or use a data class.
compareTo is only used for the < and > operators. The == operator is implemented by the separate equals function.
You can find the available operators, and the functions you need to override for each, in the Operator overloading section of the Kotlin docs.
If you don't override the equals function, the default behaviour is for it to use object identity. That means that two different objects, even if they contain the same fields, will never be considered equal.
There is however a nice shortcut for what you want to do! Kotlin will automatically generate an equals function for you if you make your class a data class. It's a good fit for classes like yours, whose main purpose is to hold data.
Because == and != translates to a call to equals(other: Any?): Boolean method, from kotlinlang
Expression Translated to
a == b a?.equals(b) ?: (b === null)
a != b !(a?.equals(b) ?: (b === null))
These operators only work with the function equals(other: Any?): Boolean, which can be overridden to provide custom equality check
implementation. Any other function with the same name (like
equals(other: Foo)) will not be called.
I have this ArrayList
var amplititudes: ArrayList<Int> = ArrayList()
amplititudes.add(1)
amplititudes.add(2)
amplititudes.add(3)
amplititudes.add(4)
amplititudes.add(3)
amplititudes.add(2)
amplititudes.add(1)
I want to get the maximum value i.e 4. What will be the easiest way to find the max element? I know about the max() method , but it will forces me to use ? with the return value since it could be null. Is there any solution which is better than this?
You can use built-in functionality with maxOrNull (docs):
val amplitudes = listOf(1,2,3,4,3,2,1)
val max = amplitudes.maxOrNull() ?: 0
max() becomes deprecated starting from Kotlin 1.4, please use maxOrNull()
val list = listOf(10, 2, 33)
val max: Int = list.maxOrNull() ?: 0
You can use max(), if you want to use the default comparison (as in your case with ints), or maxBy, if you want to use a custom selector (i.e., algorithm) to compare values.
Note that both return int? (in your case), since the collection might be empty (i.e., no maximum value is present)
max() deprecated in Kotlin 1.4.
But it was reintroduced in 1.7 . More details here
Both max() and maxOrNull() can be used.
The difference is,
max() returns non null values.If the collection is empty it will throw NoSuchElementException.
maxOrNull() returns a nullable value, so if element not present in collection it would return null.
If you are sure that collection will not be empty or you have handled exception, you can use max().Otherwise it is recommended is to use maxOrNull() and have default value if it returns null.
val amplitudes = listOf(10,8,20,15,30,90)
//Here it returns non-null int
val max:Int = amplitudes.max()
println(max) //90
//Here it returns nullable int
val max :Int? = amplitudes.maxOrNull()
println(max) //90
//Here we can make it as non-nullable type using elvis operator.
val max1 :Int = amplitudes.maxOrNull()?:0
println(max) //90
val amplitudes1 = listOf<Int>()
val max2 :Int? = amplitudes1.maxOrNull()
println(max2) //prints null
val max3:Int = amplitudes1.max()
println(max3) // Throws NoSuchElementException
Playground Link
I can't figure out what ?: does in for example this case
val list = mutableList ?: mutableListOf()
and why can it be modified to this
val list = if (mutableList != null) mutableList else mutableListOf()
TL;DR: If the resulting object reference [first operand] is not null, it is returned. Otherwise the value of the second operand (which may be null) is returned. Additionally, the operator can throw an exception if null is returned.
The Elvis operator is part of many programming languages, e.g. Kotlin but also Groovy or C#.
I find the Wikipedia definition pretty accurate:
In certain computer programming languages, the Elvis operator ?: is a binary operator that returns its first operand if that operand is true, and otherwise evaluates and returns its second operand. It is a variant of the ternary conditional operator, ? :, found in those languages (and many others): the Elvis operator is the ternary operator with its second operand omitted.
The following is especially true for Kotlin:
Some computer programming languages have different semantics for this operator. Instead of the first operand having to result in a boolean, it must result in an object reference. If the resulting object reference is not null, it is returned. Otherwise the value of the second operand (which may be null) is returned. If the second operand is null, the operator is also able to throw an exception.
An example:
x ?: y // yields `x` if `x` is not null, `y` otherwise.
x ?: throw SomeException() // yields `x` if `x` is not null, throws SomeException otherwise
The Elvis Operator is represented by a question mark followed by a colon: ?: and it can be used with this syntax:
first operand ?: second operand
It enables you to write a consise code, and works as such:
If first operand isn't null, then it will be returned. If it is null, then the second operand will be returned. This can be used to guarantee that an expression won't return a null value, as you'll provide a non-nullable value if the provided value is null.
For example(in Kotlin):
fun retrieveString(): String { //Notice that this type isn't nullable
val nullableVariable: String? = getPotentialNull() //This variable may be null
return nullableVariable ?: "Secondary Not-Null String"
}
In this case, if the computed value of getPotentialNull is not null, it will be returned by retrieveString; If it is null, the second expression "Secondary Not-Null String" will be returned instead.
Also note that the right-hand side expression is evaluated only if the left-hand side is null.
In Kotlin, you could use any expression as second operand, such as a throw Exception expression
return nullVariable ?: throw IllegalResponseException("My inner function returned null! Oh no!")
The name Elvis Operator comes from the famous American singer Elvis Presley. His hairstyle resembles a Question Mark
Source: Wojda, I. Moskala, M. Android Development with Kotlin. 2017. Packt Publishing
This is called the Elvis operator and it does... Exactly what you've described in your question. If its left hand side is a null value, it returns the right side instead, sort of as a fallback. Otherwise it just returns the value on the left hand side.
a ?: b is just shorthand for if (a != null) a else b.
Some more examples with types:
val x: String? = "foo"
val y: String = x ?: "bar" // "foo", because x was non-null
val a: String? = null
val b: String = a ?: "bar" // "bar", because a was null
Let's take a look at the defintion:
When we have a nullable reference r, we can say "if r is not null, use
it, otherwise use some non-null value x":
The ?: (Elvis) operator avoids verbosity and makes your code really concise.
For example, a lot of collection extension functions return null as fallback.
listOf(1, 2, 3).firstOrNull { it == 4 } ?: throw IllegalStateException("Ups")
?: gives you a way to handle the fallback case elgantely even if you have multiple layers of fallback. If so, you can simply chain multiply Elvis operators, like here:
val l = listOf(1, 2, 3)
val x = l.firstOrNull { it == 4 } ?: l.firstOrNull { it == 5 } ?: throw IllegalStateException("Ups")
If you would express the same with if else it would be a lot more code which is harder to read.
The elvis operator in Kotlin is used for null safety.
x = a ?: b
In the above code, x will be assigned the value of a if a is not null and b if a is null.
The equivalent kotlin code without using the elvis operator is below:
x = if(a == null) b else a
Simply we can say that, you have two hands. You want to know, is your left hand working right now?. If left hand not working, return empty else busy
Example for Java:
private int a;
if(a != null){
println("a is not null, Value is: "+a)
}
else{
println("a is null")
}
Example for Kotlin:
val a : Int = 5
val l : Int = if (a != null) a.length else "a is null"
Consider below example,
var myStr:String? = null
//trying to find out length of myStr, but it could be null, so a null check can be put as,
val len = if (myStr != null){
myStr.length
}
else{
-1
}
Using the elvis operator, the above code can be written in a single line
val len = myStr?.length ?: -1 // will return -1 if myStr is null else will return length
In addition to what has been already stated there is one good pattern that was not obvious for me, but which is common, e.g. you're writing a long function, but if something is null there is no sense to continue and the only thing you can do is to return from the function. Normally you'd write
something = expression
if (something == null) {
return
}
With elvis it becomes shorter and more elegant:
something = expression ?: return
Basically, if the left side of Elvis returns null for some reason, returns the right side instead.
i.e.
val number: Int? = null
println(number ?: "Number is null")
So, if number is NOT null, it will print number, otherwise will print "Number is null".
A little addition though is this
X = A ?: B
X will still be null if both A and B evaluate to null
Therefore, if you want X to always be non-null, make sure B is always a non-null or that B always evaluates to non-null if it's a function or expression.
Let's say I have a pointer to some object, called myObject, and I need to know, whether it is really pointing to something. How can this code:
// assume MyObjectClass *myObject;
return (BOOL)myObject;
return 112? I know, that I can always write
return (myObject == nil);
and everything will be fine. But until today I have always assumed, that explicit casting of anything to bool will always return true or false (as far as I know, 0 is always considered as false and any other value as true) and that BOOL with it's YES and NO values is just "renamed" bool. So basically, my questions are:
Why is it returning 112? :-)
Are results of explicit casting defined somewhere in C/Objective-C standard, or is it compiler-specific?
In Objective-C, the BOOL macro is just a typedef for signed char with YES/NO defined, but bool is an actual boolean, which can be true or false.
It returns 112, because it rounds the address of your pointer to signed char type.
Here is some discussion with good answers:
Objective-C : BOOL vs bool
Is there a difference between YES/NO,TRUE/FALSE and true/false in objective-c?
The definition of "true" in C is any non-zero number. Therefore 112 would be considered true as far as C is concerned. From the C99 standard:
6.3.1.2 Boolean type
When any scalar value is converted to _Bool, the result is 0 if the value compares equal
to 0; otherwise, the result is 1.
Your value is not converted to 1 because you are converting to BOOL not _Bool. The conversion to 0/1 will be technically handled inside the if (though in reality the implementation is more likely to be (myObject != 0) inside any if/while type statement).
In C , bool is a stdbool.h macro for boolean type _Bool.
And a conversion of a non-zero integer value to _Bool is guaranteed to yield 1.
That is, the result of 1 == (bool) 42 is 1.
If you are using a BOOL type as an alias for another integer type (like signed char), you can get a different result:
The result of 1 == (BOOL) 42 is 0.