What is the equivalent of Java equalsIgnoreCase in Kotlin to compare String values?
I have used equals but it's not case insensitive.
You can use equals but specify ignoreCase parameter:
"example".equals("EXAMPLE", ignoreCase = true)
As per the Kotlin Documentation :
fun String?.equals(
other: String?,
ignoreCase: Boolean = false
): Boolean
https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.text/equals.html
For Example:
val name: String = "Hitesh"
when{
name.equals("HITESH", true) -> {
// DO SOMETHING
}
}
#hluhovskyi's answer is correct, however to use it on EditText or TextView, use following -
etPassword.text.toString().equals(etConfirmPassword.text.toString(), ignoreCase = true)
In my case,
string1.contains(string2, ignoreCase = true)
This worked for me.
Becase I'm using like a search function here.
Normally, you don't need to find alternatives since Kotlin reuses existing Java types like String. Actually, these types are mapped to Kotlin internal types. In the case of String it looks like this:
java.lang.String -> kotlin.String
Therefore, the desired method equalsIgnoreCase would only be available if it was also provided in kotlin.String, which isn’t. The Kotlin designers decided to provide a more generic equals function that let's you specify the case insensitivity with a boolean parameter.
You can use the Java String class at any time if that's really necessary (it's not recommended, IntelliJ will complain about this):
("hello" as java.lang.String).equalsIgnoreCase("Hello")
With the help of an extension function, we could even add the functionality to the kotlin.String class:
fun String.equalsIgnoreCase(other: String) =
(this as java.lang.String).equalsIgnoreCase(other)
You could make an extension method:
/**
* Shortcut to compare strings while ignoring case
*/
fun String.similarTo(aString: String): Boolean {
return equals(aString,true)
}
Usage:
val upperCase = "ϴẞ"
val lowerCase = "θß"
if (upperCase.similarTo(lowerCase)) {
// Do your thing…
}
Related
I'm studying kotlin, but I'm very disappointed, I can not compare two Strings.
What is the right way to compare.
btn_login.setOnClickListener {
val login = input_email.text.trim()
val pass = input_password.text.trim()
if( login.equals( pass ) ){
startActivity<MainActivity>()
}
if (login?.equals(other = pass)){
startActivity<MainActivity>()
}
if (login == pass){
startActivity<MainActivity>()
}
}
According to documentation for structual equality use ==. It is translated to a?.equals(b) ?: (b === null).
In you case convert login and pass from SpannableStringBuilder to String.
val login = input_email.text.trim().toString()
Here is the example for matching the two strings using kotlin.
If you are using == (double equals) for matching the string then it's compare the address & return maximum time wrong result as per java documentation so use equals for the same
If you want to use equal ignore case then pass the true in the equals method of String
if (s1.equals(s2,true))
other wise you can just use this without boolean like
if (s1.equals(s2,false)) or if (s1.equals(s2))
compleate code is below
fun main(args: Array<String>) {
val s1 = "abc"
val s2 = "Abc"
if (s1.equals(s2,true))
{
println("Equal")
}
else
{
println("Not Equal")
}
}
Covert both the SpannableStringBuilder to string with toString, this should work.
val login = input_email.text.trim().toString()
val pass = input_password.text.trim().toString()
if (login == pass){
startActivity<MainActivity>()
}
1. == :
if ( string1 == string2 ){...}
2. equals :
Indicates whether some other object is "equal to" this one.
Implementations must fulfil the following requirements:
Reflexive: for any non-null reference value x, x.equals(x) should
return true.
Symmetric: for any non-null reference values x and y, x.equals(y)
should return true if and only if y.equals(x) returns true.
Transitive: for any non-null reference values x, y, and z, if
x.equals(y) returns true and y.equals(z) returns true, then
x.equals(z) should return true
Consistent: for any non-null reference values x and y, multiple
invocations of x.equals(y) consistently return true or consistently
return false, provided no information used in equals comparisons on
the objects is modified.
/** * Returns `true` if this string is equal to [other], optionally ignoring character case. * * #param ignoreCase `true` to ignore character case when comparing strings. By default `false`. */
public fun String?.equals(other: String?, ignoreCase: Boolean = false): Boolean
3. compareTo :
public override fun compareTo(other: String): Int
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.
public fun String.compareTo(other: String, ignoreCase: Boolean = false): Int
Compares two strings lexicographically, optionally ignoring case
differences
i know this is way too late, but as a newbie learning Kotlin, i had the same doubts.
then i came across this wonderful article that articulates the various string comparison types in Kotlin and the differences between them all.
in short both == and .equals() can be used to compare the value of 2 strings in kotlin.
hopefully that helps
With case checking
String a=.....
String b=.....
if(a==b){
}
IgnoreCase
if(a.equals(b,false))
KOTLIN:
if (editText1.text.toString() == editText2.text.toString() ) {
println("Should work now! The same value")
}
Try the following solution, see if it helps:
val passStr: String = textView.text.toString()
if( loginStr.compareTo(passStr, false) ){
startActivity<MainActivity>()
}
Try this surely will work.
val style = buildString { karthik}
val style2 = buildString { karthik }
var result = style.equals(style2)
if(result){//Do something}
I would like to know the difference between:
var textFieldState = remember {
mutableStateOf("")
}
and
var textFieldState by remember {
mutableStateOf("")
}
Is there any advantage over the other?
Is there any advantage over the other?
The first really should be a val and not a var. Otherwise, they are equivalent. Or, to quote the documentation:
There are three ways to declare a MutableState object in a composable:
val mutableState = remember { mutableStateOf(default) }
var value by remember { mutableStateOf(default) }
val (value, setValue) = remember { mutableStateOf(default) }
These declarations are equivalent, and are provided as syntax sugar for different uses of state. You should pick the one that produces the easiest-to-read code in the composable you're writing.
In those three:
In the first, mutableState holds a MutableState, and you use .value and .value= to manipulate the contents
In the second, value holds a MutableState, but the by syntax tells the compiler to treat it as a property delegate, so we can pretend that value just holds the underlying data
In the third, a destructuring declaration gives you getter and setter references to manipulate the content in the underlying MutableState
The by in this context is a kotlin property delegate. Any class that implements the operator fun operator fun getValue(thisRef: Any?, prop: KProperty<*>): T can use this syntax. Using = will eagerly assign the variable (importantly without delegation), the by will delegate to the operator function. The remember in this case is just a shortcut function to creating the Remember delgate that wraps the value you are creating inside the { ... } block.
A typical example is the kotlin Lazy<T> class : val myValue : Int by lazy { 1 }. If used with the by operator you will return the Int value, if used with = it will return Lazy<Int> as you have not used delegation.
It is also worth noting that delgates can be setters as well by using this operator fun : operator fun setValue(thisRef: Any?, prop: KProperty<*>, value: T).
I would like to check whether the bundle has the specified key.
Is there any modern way using kotlin to check it?
For now I was using
if(bundle.containsKey(Extras.PRODUCT){
bundle.getParcelable<Product>(Extras.PRODUCT)?.let{
mpresenter.mProduct = it
}
}
if(bundle.containsKey(Extras.ANIMAL){
bundle.getParcelable<ANIMAL>(Extras.ANIMAL)?.let{
mpresenter.mAnimal = it
}
}
... an so on
its okay if I only check one value of the Extras. But What if I have 10 or more variable in presenter. Is there any simpler solution for my case?
You could make some extension functions like
fun <T : Parcelable?> Bundle.tryGetParcelable(key: String): T? =
// getParcelable would return null anyway, but this is a general example
if (containsKey(key)) getParcelable<T>(key) else null
bundle.tryGetParcelable<Product>(Extras.PRODUCT)?.let { mPresenter.mProduct = it }
If that's still too wordy, you can pass property references and call set on those, like this:
// Upper bound isn't nullable now, since we're only assigning if the value is non-null
fun <T : Parcelable> Bundle.tryAssign(key: String, property: KMutableProperty0<T>) {
tryGetParcelable<T>(key)?.let { property.set(it) } // or let(property::set)
}
bundle.tryAssign<Product>(Extras.PRODUCT, mPresenter::mProduct)
but you might want to make the property the receiver instead, so it reads more like the usual thing = whatever
fun <T : Parcelable> KMutableProperty0<T>.tryAssign(bundle: Bundle, key: String) {
bundle.tryGetParcelable<T>(key)?.let { set(it) } // or run(::set)
}
mPresenter::mProduct.tryAssign<Product>(bundle, Extras.PRODUCT)
You'll need to make tryGetX functions for each type of Bundle getter you need, getString returns nulls but getInt always returns an Int, so it helps to have handlers that do the containsKey check so you don't need to worry about coming up with suitable, reserved default values for "not present".
If you make all those basic getter functions the same way (returning nullables) you can reuse that tryAssign function if you like, passing in the appropriate getter:
// Not using this here but it's the same getter signature, (Bundle, String) -> T?
// Note that because we're going to be passing references to these functions, we can't
// define them as extension functions in the same file - so the Bundle is a parameter now
fun tryGetString(bundle: Bundle, key: String): String? {
return bundle.getString(key)
}
// Now we're passing in the getter function we want to use, which returns a T?
// T doesn't have a Parcelable upper bound anymore
fun <T> KMutableProperty0<T>.tryAssign(bundle: Bundle, key: String, tryGet: (Bundle, String) -> T?) {
tryGet(bundle, key)?.run(::set)
}
// you won't need the type in diamond brackets, it's just for illustration
mPresenter::mProduct.tryAssign<Product>(bundle, Extras.PRODUCT, ::tryGetParcelable)
I mean, this is starting to get a bit intense, but if you have a lot of stuff to assign it might be worth having it cleanly ordered like this? Some stuff to try anyway!
Jetpack Navigation with Safe Args is now the recommended for navigating and passing data
Related Codelab Android Navigation
The navigation component has a Gradle plugin, called safe args, that
generates simple object and builder classes for type-safe access to
arguments specified for destinations and actions.
Safe args allows you to get rid of code like this when passing values
between destinations:
val username = arguments?.getString("usernameKey") And, instead,
replace it with code that has generated setters and getters.
val username = args.username
I am trying to write a function in kotlin but I am not able reassign value to function parameters ,its saying val cannot be reassigned .
class WebView{
var homepage = "https://example.com"
fun webViewLoad(url: String, preferredOrientation: String) {
if (url.equals("homepage")){
url = homepage
}
}
}
when I am trying to assign a value to url = homepage .it is giving me error val cannot be reassigned , I am new to kotlin ,I do not understand what is the issue , little help will be appreciated.
Function parameters works like val variables that couldn't be reassigned. Here you need to add variable with conditional initialization:
fun webViewLoad(url: String, preferredOrientation: String) {
val urlValue = if (url.equals("homepage")){
homepage
} else {
url
}
... //use here "urlValue" variable
}
By the way, in kotlin you don't need to use equals function to compare string: common operator == will be automatically replaced with equals in byte code.
Kotlin parameters are immutable since Kotlin M5.1
(Reference)
The main reason is that this was confusing: people tend to think that this means passing a parameter by reference, which we do not support (it is costly at runtime). Another source of confusion is primary constructors: “val” or “var” in a constructor declaration means something different from the same thing if a function declarations (namely, it creates a property). Also, we all know that mutating parameters is no good style, so writing “val” or “var” infront of a parameter in a function, catch block of for-loop is no longer allowed.
It is giving you error "val cannot be reassigned" because Kotlin function parameters are immutable i.e "val" by default. You don't need to mention the "val" keyword for it.
Quick Solution would be:
class WebView{
var homepage = "https://example.com"
fun webViewLoad(url: String, preferredOrientation: String) {
val finalUrl = if (url.equals("homepage")) homepage else url
}
}
Kotlin function parameters are final. There is no val or final keyword because that's the default (and can't be changed). Have a look at this.
By default parameters passed in the function are final what you can do is to add var. Hope it helps.
fun webViewLoad(var url: String, preferredOrientation: String) {
if (url.equals("homepage")){
url = homepage
}
}
Given an interface method like this (Android Retrofit), how do I read the URL path specified in the annotation argument from Kotlin code at runtime?
ApiDefinition interface:
#GET("/api/somepath/objects/")
fun getObjects(...)
Read the annotation value:
val method = ApiDefinition::getObjects.javaMethod
val verb = method!!.annotations[0].annotationClass.simpleName ?: ""
// verb contains "GET" as expected
// But how to get the path specified in the annotation?
val path = method!!.annotations[0].????????
UPDATE 1
Thanks for answers. I'm still struggling as I can't see what type to use to do the following:
val apiMethod = ApiDefinition::getObjects
.... then to pass that function reference into a method like this (it's reused)
private fun getHttpPathFromAnnotation(method: Method?) : String {
val a = method!!.annotations[0].message
}
IntelliJ IDE is suggesting I use KFunction5<> as a function parameter type (it doesn't exist as far as I can see) and seems to be requiring I specify all the parameter types for the method too, which makes a generic call to get the annotation attribute impossible. Isn't there a Kotlin equivalent of "Method"?, a type that will accept any method? I tried KFunction, without success.
UPDATE 2
Thanks for clarifying things. I've got to this point:
ApiDefinition (Retrofit interface)
#GET(API_ENDPOINT_LOCATIONS)
fun getLocations(#Header(API_HEADER_TIMESTAMP) timestamp: String,
#Header(API_HEADER_SIGNATURE) encryptedSignature: String,
#Header(API_HEADER_TOKEN) token: String,
#Header(API_HEADER_USERNAME) username: String
): Call<List<Location>>
Method to retrieve annotation argument:
private fun <T> getHttpPathFromAnnotation(method: KFunction<T>) : String {
return method.annotations.filterIsInstance<GET>().get(0).value
}
Call to get the path argument for a specific method:
val path = getHttpPathFromAnnotation<ApiDefinition>(ApiDefinition::getLocations as KFunction<ApiDefinition>)
The implicit cast seems to be necessary or the type parameter demands I provide a KFunction5 type.
This code works, but it has the GET annotation hard-coded, is there a way to make it more generic? I suspect I might need to look for GET, POST and PUT and return the first match.
Use the Kotlin KFunction directly instead of javaMethod (you're using Kotlin anyway!), and findAnnotation for concise, idiomatic code.
This will also work if the annotation happens to not be the first, where annotations[0] may break.
val method = ApiDefinition::getObjects
val annotation = method.findAnnotation<GET>() // Will be null if it doesn't exist
val path = annotation?.path
Basically all findAnnotation does is return
annotations.filterIsInstance<T>().firstOrNull()