Android - 是不是可以使用 Comparator.comparing 而不是 API < 24 上的自定义比较器对列表进行排序?

Posted

技术标签:

【中文标题】Android - 是不是可以使用 Comparator.comparing 而不是 API < 24 上的自定义比较器对列表进行排序?【英文标题】:Android - Is it possible to sort lists using Comparator.comparing instead of custom Comparators on APIs < 24?Android - 是否可以使用 Comparator.comparing 而不是 API < 24 上的自定义比较器对列表进行排序? 【发布时间】:2018-07-16 19:39:43 【问题描述】:

我正在开发的应用程序中有一个 RecyclerView,我可以填充各种项目和搜索/过滤/排序/等等。目前正在进行排序。

我有多个可以排序的条件,可以从下拉微调器中选择。在数据对象中排序的值包括字符串、整数和枚举,所有这些都相当容易排序。然而,虽然有些排序选项只需要一个标准,但有些则需要二级或三级标准(在一些非常罕见的情况下最多可达 4 个)。为了有效地使用Collections.sort(List, Comparator),我必须编写大量的自定义比较器,所以我希望有一些方法可以避免这种情况。

事实证明,Java 8 有一个很好的解决方案:Comparator.comparing(...),它会为您生成比较器,并且可以通过Comparator.comparing().thenComparing().thenComparing()... 轻松无限地扩展。它还有List myList.sort(),与Collections.sort(myList)相比,我不确定它的效率,但对我来说感觉更干净。我调查了一下,认为只是我的运气! android 已经支持许多 Java 8 功能有一段时间了!

不幸的是,Android Studio 告诉我,出于某种原因,Comparator.comparing()List::sort 仅支持 API 24 及更高版本。这对我来说实际上行不通,因为我正在开发的应用程序“需要”运行低至 API 15-16。然而,我觉得这很奇怪,因为我尝试过的其他 Java 8 功能(像 (o1, o2) -&gt; (o1.toString().compareTo(o2.toString()) 这样的 lambda 表达式和像上面的 List::sort 这样的方法引用)在我检查过的范围内的所有 API 级别上都可以正常工作,只要你指定以 Java 8 为目标。毕竟它是 Java 8 的东西,而不是 Android 的东西。

考虑到所有这些,有没有办法让Comparator.comparing()List::sort 在 API 24 下工作?我在 Google 搜索中没有找到任何内容,它们最终都只是指向 Android 的 Java 8“文档”或用于比较器和列表的 JavaDocs。要么是 Android 的支持库之一(似乎不太可能),要么是像 Retrolambda 这样的第三方库/黑客?

【问题讨论】:

第三方反向移植:streamsupport。只需将compile 'net.sourceforge.streamsupport:streamsupport:1.6.1' 添加到您的build.gradle。更好的是:如果你使用 Android Studio 3.x (desugar toolchain),你也可以尝试使用android-retrostreams,这是一个针对 Android Studio 3.x 开发者的流支持分支(它的 API 更符合官方Java 8/9 API 可能的情况下)。在这种情况下添加compile 'net.sourceforge.streamsupport:android-retrostreams:1.6.1' java8.util.Lists#sort, java8.util.Comparators = 流支持。 java9.util.Lists#sort, java9.util.Comparators = android-retrostreams. 注意包名的区别,java8.util (streamsupport) 和 java9.util (android-retrostreamms)。 Java 8/9 的新接口在 android-retrostreams 中有默认/静态方法,但在流支持中没有(你必须使用所谓的 companion classes 【参考方案1】:

尝试将一些 java 8 功能移植到 java 6/7 的 streamsupport 库: https://github.com/streamsupport

他们有你需要的课程: https://github.com/streamsupport/streamsupport/blob/master/src/main/java/java8/util/Comparators.java (它从 Comparator 重命名为 Comparators 只是为了避免名称冲突)。

【讨论】:

+1。我认为您还应该提及android-retrostreams。对于使用 Android Studio 3.x 的开发人员来说,这甚至更好。例如,函数式接口有其真正的 Java 8 defaultstatic 方法。 Java 8 Stream API 中添加的所有其他接口也是如此。 这正是我所希望的!根据@Sartorius 的建议,我使用了 android-retrostreams。与 Android Studio 3+ 集成非常好用。【参考方案2】:

目前只有一小部分 Java8 操作在 Android 上完全向后兼容。 https://developer.android.com/studio/write/java8-support.html#supported_features

但是,您可以获得几乎所有的 java8 功能,这些功能也向后兼容 Kotlin。使用 Kotlin 或 RxJava 是一种选择吗?它们都支持过滤器方法。

如果您有一个列表,并且想要过滤用户名和电子邮件,您可以执行类似的操作

科特林:

list.filterit.username.contains(filterString).filterit.email.length > 4

Rx 的工作量稍大一些,因为它必须在作为实际列表使用之前进行转换,但对于 Java 或 Kotlin 的正确语法,它本质上是相同的。

【讨论】:

我从未使用过 Kotlin,因此虽然这并没有明确排除它,但它对我来说不太可用。我首先考虑使用 RxJava,但由于我也不熟悉它,我只能看到它使工作流程更加复杂,而不是更少。我只是选择了使用第三方 android-retrostreams 库进行编译的公认解决方案。 我建议学习 Kotlin。对于已经了解 Java 的开发人员来说,通常只需要一两天的时间。开发人员贡献/开源的许多代码都是用 Kotlin 编写的,更不用说它是由 Google 和 Jetbrains 所设想的,它们是制作 Android 和您的 IDE 的人。与使用第三方库相比,您将获得更好的长期支持,以及更少的方法计数(假设您将在某个时候添加 Kotlin)。

以上是关于Android - 是不是可以使用 Comparator.comparing 而不是 API < 24 上的自定义比较器对列表进行排序?的主要内容,如果未能解决你的问题,请参考以下文章

Java自然排序 Comparable的使用

android - 是不是可以使用私有意图而不是全局意图?

Android:是不是可以使用数字更新 ImageView/ImageButton 以显示新消息的数量?

Android:是不是有任何解决方案可以每次使用 GPS 或网络获取准确位置 [重复]

Android 动态创建View,是不是可以使用 style,如何使用?

Android开发:是不是可以回滚到Eclipse?