是否可以在<24的Android API上使用Java 8 Stream API?


89

我在这里读了这篇文章。但是我仍然无法在minSdkVersion <24上运行包含以下Java 8 Stream API功能的代码。

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

由于错误消息,此命令无法运行

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

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


3
不,您不能使用api 24以下的java流。虽然有这项工作,但是有实现相同功能的第三方库
tyczj

1
我有一个小型图书馆,为下层api做类似的事情:github.com/smaspe/FunctionalIterables
njzk2 2013年

2
有关类似的问题(和答案),请参见stackoverflow.com/questions/39265004/…stackoverflow.com/questions/39039566/…
Sartorius

3
@PEMapModder您可以使用面向Android的新Jack编译器(甚至可以追溯到Gingerbread)使用lambda表达式和方法引用。什么,你不能有SDK 24以下是默认/静态接口方法和Java 8特定的API,如流API。
Sartorius

您可以使用StreamSupport类下API 24
泽尔奥兹坎

Answers:


69

[原始答案]

您不能在API级别<24上使用Java8流。

但是,有些库可以反向移植某些流功能

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]

好消息,现在我们可以使用Java 8 Stream API以及更多功能,而无需最低的API级别


9
尽管solidLightweight-Stream-API对于类似Stream的编程无疑是有价值的选项,但是恕我直言,它们甚至都不能被远程视为Java 8 Stream API的“反向”。我知道的唯一可以声称与Java 8流在语法和功能上均相近的项目streamsupport。例如,它还支持并行流。尽管这对于Android开发人员而言可能并不那么重要。
Sartorius

IMO,由于Gradle支持,Lightweight-Stream-API是Android上最好的API,并添加了“ select”,“ groupBy”等附加功能。github.com/aNNiMON/Lightweight-Stream-API #additional-operators
LordParsley '17

2
@LordParsley streamsupport还具有Gradle支持。至于演员,是的。据我了解,从官方Java 8 API进行扩展/转移从来都不是streamsupport的设计目标。
Sartorius

3
@Sartorius是正确的–我建议查看Github镜像以获取用法详细信息和Gradle参考github.com/streamsupport/streamsupport
LordParsley,2017年

我读过,一般而言,Java Streams比集合慢。stackoverflow.com/questions/22658322 / ...这些反向端口呢?
Shikhar Shrivastav '18

12

DexGuard 8.2版开始,可以在<API级别24的Android设备上使用Java 8流API。为此,需要包含流支持库,并且DexGuard会将所有Java 8流API调用转换为所提供的图书馆。无需其他处理,开发人员只需使用提供的Java 8流API进行编码即可。依赖关系也会自动翻译,因此可以将具有Java 8功能的库用于Android开发。

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

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


它不是官方图书馆
user25

我对图书馆本身并不了解,但是我建议在用于商业项目之前,先检查图书馆的许可证。GNU通用公共许可证,版本2,带有Classpath Exception。可能必须确认一层。
Michal Harakal

5
@MichalHarakal,我花了几秒钟才意识到该实际上是律师:)
superjos

6

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

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

3
@AjahnCharles告诉人们在有关语言A的问题时仅使用语言B不是一个好答案。许多项目仍使用Java编写。
mkuech

2
@AjahnCharles您很好地吸引了读者的注意力,可能要考虑对Android生态系统的更改。也就是说,问题在于Java的特定功能,而Java仍是Android开发的官方支持语言。开关,即使“只”杂交你的应用程序,带来了成本(学习曲线,也许他们的团队不支持等),需要在深入研究的方式多问什么的问题。更重要的是,该评论并未解决Kotlin如何成为解决方案的问题,这使它变得更加脱离上下文,也没有太大帮助。
mkuech

3
@AjahnCharles明确提及时Java 8 Stream API,我认为,答案也应该在JAVA中!
Abhriya Roy

1

是的,是!从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'
}

-1

我想使用的另一种解决方案是,如果项目同时支持Kotlin从Java代码的Collections的扩展,则可以静态地使用它们

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

同为.map.reduce.first,...等


-6

创建一个İnterface。

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"));
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.