Ist es möglich, die Java 8 Stream API auf der Android API <24 zu verwenden?

87

Ich habe diesen Beitrag hier gelesen . Trotzdem kann ich auf minSdkVersion <24 keinen Code ausführen, der Java 8 Stream-API-Funktionen wie die folgenden enthält.

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

Dies wird aufgrund der Fehlermeldung nicht ausgeführt

Für den Aufruf ist API-Level 24 erforderlich (aktuell mindestens 15): java.util.Collection # stream

Kennt jemand eine Lösung?

unbegrenzt101
quelle
3
Nein, Sie können den Java-Stream unter API 24 nicht verwenden. Es gibt Bibliotheken von Drittanbietern, die das Gleiche implementieren, obwohl dies funktioniert
tyczj
1
Ich habe eine kleine Bibliothek, die ähnliche Dinge für untere Apis tut: github.com/smaspe/FunctionalIterables
njzk2
2
Ähnliche Fragen (und Antworten) finden Sie unter stackoverflow.com/questions/39265004/… und stackoverflow.com/questions/39039566/… .
Sartorius
3
@PEMapModder Mit dem neuen Jack-Compiler für Android können Sie Lambda-Ausdrücke und Methodenreferenzen verwenden, die bereits auf Gingerbread abzielen. Was Sie unter SDK 24 nicht haben können, sind Standard- / statische Schnittstellenmethoden und Java 8-spezifische APIs wie die Stream-API.
Sartorius
Sie können die StreamSupport-Klasse unter API 24
Özer Özcan

Antworten:

65

[ursprüngliche Antwort]

Sie können keine Java8-Streams auf API-Ebene <24 verwenden.

Es gibt jedoch einige Bibliotheken, die einige der Stream-Funktionen zurückportieren

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

https://github.com/konmik/solid

https://sourceforge.net/projects/streamsupport/ (von @sartorius im Kommentar erwähnt)

[Update k3b 2019-05-23]

https://github.com/retrostreams/android-retrostreams ist ein Spin-off von Streamsupport, das die Fähigkeit der Android Studio 3.x D8 / Desugar-Toolchain nutzt, Standard- und statische Schnittstellenmethoden über Jar-Dateigrenzen hinweg zu verwenden. Es gibt auch Links zu anderen Android-RetroXXX, dh für CompletableFuture.

[Aeracode 2020-07-24 aktualisieren]

Gute Nachrichten , jetzt können wir Java 8 Stream API und mehr verwenden, ohne dass eine Mindest-API-Ebene erforderlich ist .

Robert Estivill
quelle
9
Während Solid und Lightweight-Stream-API sicherlich wertvolle Optionen für die Stream-ähnliche Programmierung sind, kann meiner Meinung nach keine von ihnen auch nur aus der Ferne als "Backport" der Java 8 Stream-API betrachtet werden. Das einzige Projekt, von dem ich weiß, dass es in der Syntax und der Funktionalität von Java 8-Streams vergleichbar ist, ist die Streamsupport . Beispielsweise werden auch parallele Streams unterstützt. Obwohl dies für Android-Entwickler möglicherweise nicht so wichtig ist.
Sartorius
IMO, war Leichtbau-Stream - API-die schönste auf Android wegen der Gradle Unterstützung und Extras wie „wählen“, „groupBy“ usw. github.com/aNNiMON/Lightweight-Stream-API#additional-operators .
LordParsley
2
@ LordParsley Streamsupport bietet auch Gradle-Unterstützung. Was die Extras betrifft, stimmt das. Soweit ich weiß, war das Erweitern / Umleiten von der offiziellen Java 8-API nie ein Entwurfsziel der Streamsupport.
Sartorius
3
@Sartorius ist richtig - ich empfehlen , den Github Spiegel für Nutzungsdetails und der Gradle Refs github.com/streamsupport/streamsupport
LordParsley
Ich habe gelesen, dass Java Streams im Allgemeinen langsamer sind als Sammlungen. stackoverflow.com/questions/22658322/… Was ist mit diesen Backports?
Shikhar Shrivastav
12

Seit Release 8.2 von DexGuard ist es möglich, die Java 8-Streams-API auch auf Android-Geräten <API-Ebene 24 zu verwenden. Dazu muss die Streamsupport- Bibliothek enthalten sein, und DexGuard übersetzt alle Java 8-Stream-API-Aufrufe in die bereitgestellten Bibliothek. Es ist keine zusätzliche Behandlung erforderlich, und Entwickler können einfach mithilfe der bereitgestellten Java 8-Streams-API codieren. Abhängigkeiten werden ebenfalls automatisch übersetzt, sodass Bibliotheken mit Java 8-Funktionen auch für die Android-Entwicklung verwendet werden können.

Diese Funktion wird in naher Zukunft auch in ProGuard enthalten sein. Bleiben Sie dran.

Bearbeiten: Proguard 6.1.0, für das es bereits eine Beta-Version gibt, unterstützt das Backportieren von Java 8-Streams und der Zeit-API.

T. Neidhart
quelle
Es ist keine offizielle Bibliothek
user25
Ich habe keine wirkliche Ahnung von der Bibliothek selbst, aber ich würde empfehlen, die Lizenz der Bibliothek vor der Verwendung in einem kommerziellen Projekt zu überprüfen. GNU General Public License, Version 2, mit der Classpath-Ausnahme . Wahrscheinlich muss eine Schicht bestätigen.
Michal Harakal
5
@MichalHarakal Es dauerte ein paar Sekunden, bis mir klar wurde, dass es sich bei der Schicht tatsächlich um einen Anwalt handelte :)
Superjos
6

Könnte etwas spät zur Party kommen, aber ich habe gerade gesehen, dass wir, wenn wir verwenden, java8.util.stream.StreamSupportdenselben funktionalen Programmieransatz ausführen und ihn vor Api 24 verwenden können. ZB aus web3j -

StreamSupport.stream(transactionReceipt.getLogs())
            .map(log -> extractEventParameters(event, log))
            .filter(Objects::nonNull)
            .collect(Collectors.toList());
Abhriya Roy
quelle
3
@AjahnCharles Es ist keine gute Antwort, den Leuten zu sagen, dass sie nur Sprache B verwenden sollen, wenn es um Sprache A geht. Viele Projekte sind noch in Java geschrieben.
mkuech
2
@AjahnCharles Sie machen einen guten Punkt, um die Aufmerksamkeit der Leser darauf zu lenken, möglicherweise Änderungen am Android-Ökosystem in Betracht zu ziehen. Die Frage bezieht sich jedoch auf eine bestimmte Funktion von Java, die immer noch eine offiziell unterstützte Sprache für die Android-Entwicklung ist. Das Wechseln, selbst wenn "nur" das Hybridisieren Ihrer App mit Kosten verbunden ist (Lernkurve, möglicherweise wird es von ihrem Team nicht unterstützt usw.), und dies erfordert mehr Eintauchen in das , was in der Frage gestellt wird. Noch wichtiger ist, dass der Kommentar nicht darauf eingeht, wie Kotlin eine Lösung ist, was es unzusammenhängender und weniger hilfreich macht.
12.
3
@ AjahnCharles Wenn es klar erwähnt wird Java 8 Stream API, denke ich, sollte die Antwort auch in JAVA sein!
Abhriya Roy
0

Ja, das ist es ! Ausgehend von AGP 4.0.0 wir Stream - API verwenden können , und einige andere Java 8+ APIs (zB java.time)

Minimal erforderliche Änderungen am build.gradle Ihrer App :

android {
  compileOptions {
    // Flag to enable support for the new language APIs
    coreLibraryDesugaringEnabled true
  }
}

dependencies {
  coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.0.9'
}
Aeracode
quelle
-1

Eine andere Lösung, die ich gerne verwende, ist die statische Verwendung von Kotlins Erweiterungen über Sammlungen aus Java-Code, wenn das Projekt natürlich beide unterstützt :

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

Das Gleiche gilt für .map, .reduce, .first, ... usw.

y.allam
quelle
-7

Erstellen Sie eine Schnittstelle.

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

Erstellen Sie eine Filtermethode.

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

Verwenden von Code

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