问题 Android - 是否可以使用Comparator.comparing而不是API


我在我正在开发的应用程序中有一个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功能(lambda表达式如 (o1, o2) -> (o1.toString().compareTo(o2.toString()) 和方法参考 List::sort 只要你指定目标Java 8,我就可以在我检查的范围内的所有API级别上正常工作。毕竟它是Java 8的东西,而不是Android的东西。

所以考虑到所有这些,有没有办法 Comparator.comparing() 和 List::sort 在API 24以下工作?我在谷歌的搜索中没有找到任何东西,它们最终只是指向Android的Java 8“文档”或者指向Comparator和List的JavaDocs。在Android的一个支持库(似乎不太可能)或第三方库/ hack之类的东西 Retrolambda


8640
2018-02-06 16:56


起源

第三方后门: streamsupport。只需添加 compile 'net.sourceforge.streamsupport:streamsupport:1.6.1' 到你的 build.gradle。更好的是:如果您使用Android Studio 3.x(desugar工具链),您也可以尝试使用 Android的retrostreams 这是针对Android Studio 3.x开发人员的一个streamsupport分支(它的API更符合官方Java 8/9 API,这是可能的)。在那种情况下添加 compile 'net.sourceforge.streamsupport:android-retrostreams:1.6.1'。 - Sartorius
java8.util.Lists#排序, java8.util.Comparators = streamsupport。 java9.util.Lists#排序, java9.util.Comparators = android-retrostreams。 - Sartorius
请注意包名称java的区别8.util(streamsupport)与java9.util(android-retrostreamms)。 Java 8/9中新增的接口在android-retrostreams中有默认/静态方法,但在streamsupport中没有(你必须使用所谓的接口) 伴侣班) - Sartorius


答案:


尝试使用streamsupport库将一些java 8特性移植到java 6/7: https://github.com/streamsupport

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


7
2018-02-06 17:22



+1。我想你也应该提一下 Android的retrostreams。对于使用Android Studio 3.x的开发人员来说,这甚至更好。例如,功能接口具有真正的Java 8 默认 和 静态的 方法。对于Java 8 Stream API中添加的所有其他接口也是如此。 - Sartorius
这正是我所希望的!根据@Sartorius的建议,我使用了android-retrostreams。功能强大且易于与Android Studio 3+集成。 - VerumCH


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

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

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

科特林:

list.filter{it.username.contains(filterString)}.filter{it.email.length > 4}

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


2
2018-02-06 17:12



我从来没有使用过Kotlin,所以虽然没有明确地将它排除在外,但它对我来说不太可用。我考虑首先使用RxJava,但由于我也不熟悉它,我只能看到它使工作流程更复杂,而不是更少。我刚刚接受了与第三方android-retrostreams库一起编译的公认解决方案。 - VerumCH
我建议学习Kotlin。对于已经了解Java的开发人员来说,通常只需要一两天即可。许多开发人员正在贡献/开源的代码正在Kotlin中编写,更不用说谷歌和Jetbrains,制造Android和你的IDE的人。假设您要在某个时刻添加Kotlin,那么您将获得比使用第三方库更好的长期支持,以及更低的方法计数。 - Dan Hartman