【问题标题】:Is it possible to use the Java 8 Stream API on Android API < 24?是否可以在 Android API < 24 上使用 Java 8 Stream API?
【发布时间】:2017-01-23 17:04:46
【问题描述】:

我在这里读过post。但我仍然无法在 minSdkVersion

List<Car> newCars = cars.stream()
                        .filter(s -> s.getColor().equals("red"))
                        .collect(Collectors.toList());

由于错误消息而无法运行

调用需要 API 级别 24(当前最低为 15):java.util.Collection#stream

那么有人知道解决方案吗?

【问题讨论】:

  • 不,您不能使用低于 api 24 的 java 流。有 3rd 方库可以实现相同的功能
  • 我有一个小型库,可以为较低的 api 做类似的事情:github.com/smaspe/FunctionalIterables
  • @PEMapModder 您可以使用针对 Android 的新 Jack 编译器使用 lambda 表达式和方法引用,最早可以追溯到 Gingerbread。您在 SDK 24 下不能拥有的是默认/静态接口方法和 Java 8 特定 API,例如 Stream API。
  • API 24 下可以使用 StreamSupport 类

标签: java android java-8 java-stream


【解决方案1】:

[原答案]

您不能在 API 级别

但是,有些库支持某些流功能

https://github.com/aNNiMON/Lightweight-Stream-API

https://github.com/konmik/solid

https://sourceforge.net/projects/streamsupport/(@sartorius 在评论中提到)

[更新 k3b 2019-05-23]

https://github.com/retrostreams/android-retrostreams 是 streamsupport 的衍生产品,它利用 Android Studio 3.x D8 / desugar 工具链跨 Jar 文件边界使用接口默认和静态方法的能力。还有其他 android-retroXXX 的链接,例如 CompletableFuture。

[更新 aeracode 2020-07-24]

Good news,现在我们可以使用 Java 8 Stream API 等无需最低 API 级别

【讨论】:

  • 虽然 solidLightweight-Stream-API 对于类似 Stream 的编程来说无疑是有价值的选择,但恕我直言,它们甚至都不能被视为 Java 8 Stream API 的“反向移植”。我知道的唯一一个可以声称在语法和功能上与 Java 8 流相当的项目是streamsupport。例如,它还支持并行流。虽然这对 Android 开发者来说可能不是那么重要。
  • IMO,Lightweight-Stream-API 是 Android 上最好的,因为 Gradle 支持并添加了“select”、“groupBy”等附加功能。github.com/aNNiMON/Lightweight-Stream-API#additional-operators
  • @LordParsley 流支持也有 Gradle 支持。至于额外的东西,是的,这是真的。据我了解,从官方 Java 8 API 扩展/转移从来都不是流支持的设计目标。
  • @Sartorius 是对的——我建议查看 Github 镜像以了解使用详情和 Gradle 参考资料github.com/streamsupport/streamsupport
  • 我读到过,Java Streams 通常比集合慢。 stackoverflow.com/questions/22658322/… 这些反向移植怎么样?
【解决方案2】:

DexGuard 8.2 版开始,也可以在 streamsupport 库,DexGuard 将翻译所有 Java对提供的库的 8 个流 API 调用。不需要额外的处理,开发人员可以使用提供的 Java 8 流 API 进行简单的编码。依赖项也会自动翻译,因此也可以将具有 Java 8 功能的库用于 Android 开发。

该功能也将在不久的将来包含在 ProGuard 中,敬请期待。

编辑:已经存在测试版的 Proguard 6.1.0 支持向后移植 Java 8 流和时间 API。

【讨论】:

  • 不是官方图书馆
  • 我对库本身并不了解,但我建议在用于商业项目之前检查库的许可证。 GNU 通用公共许可证,版本 2,带有类路径例外。可能需要确认一层。
  • @MichalHarakal 我花了几秒钟才意识到 layer 实际上是 lawyer :)
  • 由于proguard,我们的应用程序在发布版本中因脱糖而崩溃,知道如何解决吗?这是 SO 问题stackoverflow.com/q/67656105/12204620
【解决方案3】:

创建一个接口。

public interface Pre<T,R> {
            R get(T item);
        }

创建过滤方法。

public static  <T> List<T> Filter(List<T> list, Pre<T,Boolean> pre) {

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
        {
            return list.stream().filter(p -> pre.get(p)).collect(Collectors.toList());
        }
        else
        {
            List<T> col = new ArrayList<T>();
            for (int i = 0 ; i < list.size() ; i++)
                if (pre.get(list.get(i)))
                    col.add(list.get(i));
            return col;
        }
    }

使用代码

    public static class model {
            public String Name;
        }
List<model> models = new ArrayList<>();
            ...
            List<model> filtermodels = Filter(models,p-> p.Name.equals("filter"));

【讨论】:

    【解决方案4】:

    可能有点晚了,但我刚刚看到如果我们使用java8.util.stream.StreamSupport,那么我们可以运行相同的函数式编程方法并在 Api 24 之前使用它。例如取自 web3j -

    StreamSupport.stream(transactionReceipt.getLogs())
                .map(log -> extractEventParameters(event, log))
                .filter(Objects::nonNull)
                .collect(Collectors.toList());
    

    【讨论】:

    • @AjahnCharles 当他们的问题是关于语言 A 时,告诉人们只使用语言 B 并不是一个好的答案。许多项目仍然是用 Java 编写的。
    • @AjahnCharles 考虑到 Android 生态系统的变化,您提出了一个很好的观点,即吸引读者注意可能。也就是说,问题是关于 Java 的一个特定功能,它仍然是 Android 开发的官方支持语言。切换,即使“仅”混合您的应用程序,也会带来成本(学习曲线,也许他们的团队不支持它等),并且需要深入方式而不是题。更重要的是,该评论没有说明如何 Kotlin 是一种解决方案,这使得它更加脱离上下文并且不太有用。
    • @AjahnCharles 当明确提到Java 8 Stream API,我感觉,答案也应该是JAVA!
    【解决方案5】:

    我喜欢使用的另一个解决方案是静态使用 Kotlin 的扩展而不是 Java 代码中的集合,如果项目同时支持这两者

    List<Car> newCars = CollectionsKt.filter(cars, s -> s.getColor().equals("red"));
    

    .map.reduce.first、...等也一样

    【讨论】:

      【解决方案6】:

      Yes, it is!从 AGP 4.0.0 开始,我们可以使用 Stream API 和其他一些 Java 8+ API(例如 java.time

      对您的应用的build.gradle进行最少的更改:

      android {
        compileOptions {
          // Flag to enable support for the new language APIs
          coreLibraryDesugaringEnabled true
        }
      }
      
      dependencies {
        coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.0.9'
      }
      

      【讨论】:

        猜你喜欢
        • 2016-06-26
        • 2016-08-10
        • 1970-01-01
        • 2020-12-10
        • 2016-07-06
        • 1970-01-01
        • 2017-02-12
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多