【问题标题】:Sort array by alphabet using Kotlin使用 Kotlin 按字母对数组进行排序
【发布时间】:2018-11-17 12:57:10
【问题描述】:

我正在为我的手机制作一个启动器,我需要按字母对应用程序进行排序。

 Appslist = ArrayList<AppInfo>()

    val i = Intent(Intent.ACTION_MAIN, null)
    i.addCategory(Intent.CATEGORY_LAUNCHER)
    val allApps = this.packageManager.queryIntentActivities(i, 0)

    for (ri in allApps) {
        val app = AppInfo()
        app.label = ri.loadLabel(this.packageManager)
        app.packageName = ri.activityInfo.packageName
        app.icon = ri.activityInfo.loadIcon(this.packageManager)
        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)
            }
        }

    }

这是我的列表类型(不知道是不是叫列表类型,但希望你能理解):

public class AppInfo {
internal var label: CharSequence? = null
internal var packageName: CharSequence? = null
internal var icon: Drawable? = null
internal var isInFav: Boolean? = false

【问题讨论】:

  • 使用 Collections.sort(your_list) 这会给你排序列表
  • @pratikvekariya 您的评论不正确,它是未实现 Comparable 的类的列表,因此没有自然顺序,您的方法失败,此外它对于 Kotlin 来说也不是惯用的。跨度>
  • 大卫,您的问题得到解答还是在寻找其他东西?
  • 是的。 ( :

标签: kotlin


【解决方案1】:

如果要排序到列表的副本中,惯用的方法是使用ListsortedBy 扩展方法。如果您想在没有副本的情况下就地排序,或者在 MutableList 上使用 sortBy 扩展名。 ArrayList 可以用作任一列表类型。

// Sort a readonly list into a copy of the list

val appsList: List<AppInfo> = ...

val sortedAppsList = appsList.sortedBy { it.label?.toString() }

对比:

// Sort a mutable list in-place

val appsList: MutableList<AppInfo> = ...

appList.sortBy { it.label?.toString() }

如果作为ArrayList 持有,它是相同的,但不习惯直接引用此具体类型。

// 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() }

注意label: CharSequence 成员上的toString()。您必须小心对 CharSequence 类型的引用进行排序,因为它未定义其排序行为(请参阅:https://docs.oracle.com/javase/7/docs/api/java/lang/CharSequence.html

这个接口没有细化 equals 和 hashCode 方法的一般合约。因此,比较实现 CharSequence 的两个对象的结果通常是未定义的。

如果CharSequence 已经是String(很可能是),那么调用toString() 并没有什么坏处,因为它只是返回自身。

还请记住,还必须处理可以为空的CharSequence,并且您需要决定在哪里需要空值:在列表的开头或结尾。我认为他们的默认设置是从头开始。


关于问题中代码的其他说明:

使用 ListMutableList 接口而不是具体类来引用类型,并使用 Kotlin stdlib 中的方法对列表执行操作。对于不会改变的引用,也可以使用val 而不是var这意味着无论列表内容是否会改变,它都会始终指向同一个列表)。

你拥有的if 声明可以减少很多,从...

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)
    }
}

更简单:

if (app.packageName != "com.david.launcher" &&
        (searchWord.isBlank() || 
         app.label?.startsWith(searchWord, ignoreCase = true) == true)) {
    appsList.add(app)
}

您应该browse the standard library 了解可用的内容,以便为未来扩展您的工具包。

【讨论】:

    【解决方案2】:
    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
        }
    

    【讨论】:

      【解决方案3】:

      您可以使用 Collections.sort() 和在 AppInfo.label 上运行的 Comparator&lt;AppInfo&gt; 的自定义实现来执行此操作,或者使 AppInfo 类实现 Comparable 接口并以仅比较的方式实现 compareTo 方法标签字段。

      【讨论】:

      • 这个答案不完整,因为它是一个更复杂的问题。首先,可用于排序的数据类型是不可排序的(CharSequence),并且它不是惯用的 Kotlin 类型,创建一个 Comparator 只是为了一次性排序,也不是为了一次性将 Comparable 添加到类中种类。考虑到类中的所有类型都可以为空,还必须考虑空处理。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-02-28
      • 1970-01-01
      • 2019-06-15
      • 1970-01-01
      相关资源
      最近更新 更多