Sort array by alphabet using Kotlin
class CustomClass {
var id: String = ""
var name: String = ""
}
fun sortAlphabetically(arrayList: ArrayList< CustomClass >): ArrayList< CustomClass >{
var returnList: ArrayList< CustomClass > = arrayListOf()
var list = arrayList as MutableList< CustomClass >
list.sortWith(Comparator { o1: CustomClass, o2: CustomClass ->
o1.name.compareTo(o2.name)
})
returnList = list as ArrayList< CustomClass >
return returnList
}
The idiomatic way is to use the sortedBy
extension method for List
if you want to sort into a copy of the list. Or use sortBy
extension on a MutableList
if you want to sort in-place without a copy. An ArrayList
would work as either list type.
// Sort a readonly list into a copy of the list
val appsList: List<AppInfo> = ...
val sortedAppsList = appsList.sortedBy { it.label?.toString() }
versus:
// Sort a mutable list in-place
val appsList: MutableList<AppInfo> = ...
appList.sortBy { it.label?.toString() }
and if holding as an ArrayList
it is the same, but not idiomatic to have a reference directly to this concrete type.
// Sort an ArrayList list into a copy of the list
val appsList: ArrayList<AppInfo> = ... // ALERT! not idiomatic
val sortedAppsList = appsList.sortedBy { it.label?.toString() }
// or if you want, feel free to sort in-place
appsList.sortBy { it.label?.toString() }
Note the toString()
on the label: CharSequence
member. You have to be careful sorting on a reference of type CharSequence
as it is undefined what is its behavior for sorting (see: https://docs.oracle.com/javase/7/docs/api/java/lang/CharSequence.html)
This interface does not refine the general contracts of the equals and hashCode methods. The result of comparing two objects that implement CharSequence is therefore, in general, undefined.
If the CharSequence
is already a String
(likely is), then there is no harm in calling toString()
as it just returns itself.
Also keep in mind that the nullable CharSequence
has to be handled as well, and you need to decide where you want nulls: at the start or end of the list. I think the default is for them to go to the start.
Other notes about your code in the question:
Use the List
or MutableList
interface instead of the concrete class to reference the type, and use the methods from Kotlin stdlib to do actions upon the list. Also use val
instead of var
for references that will not change (meaning it will always point to the same list regardless of whether the list contents could change).
The big if
statement you have can be reduced a lot, go from...
if(app.label?.toString()!!.length >= searchWord.length && app.label?.toString()!!.substring(0, searchWord.length) == searchWord.toUpperCase() && searchWord != "" ||
app.label?.toString()!!.length >= searchWord.length && app.label?.toString()!!.substring(0, searchWord.length) == searchWord.toLowerCase() && searchWord != "" ||
app.label?.toString()!!.length >= searchWord.length && app.label?.toString()!!.substring(0, searchWord.length) == searchWord.capitalize() && searchWord != "" ||
app.label?.toString()!!.length >= searchWord.length && app.label?.toString()!!.substring(0, searchWord.length) == searchWord && searchWord != ""){
if(app.packageName != "com.david.launcher" ){
Appslist.add(app)
}
}
if(searchWord == ""){
if(app.packageName != "com.david.launcher"){
Appslist.add(app)
}
}
to simpler:
if (app.packageName != "com.david.launcher" &&
(searchWord.isBlank() ||
app.label?.startsWith(searchWord, ignoreCase = true) == true)) {
appsList.add(app)
}
You should browse the standard library to get an idea of what is available so that you broaden your toolkit for the future.