È possibile utilizzare l'API Java 8 Stream su API Android <24?


89

Ho letto questo post qui. Ma ancora non riesco a eseguire codice contenente le funzionalità API Java 8 Stream come le seguenti su minSdkVersion <24.

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

Non viene eseguito a causa del messaggio di errore

La chiamata richiede il livello API 24 (il valore minimo corrente è 15): java.util.Collection # stream

Quindi qualcuno conosce una soluzione?


3
no, non puoi usare il flusso java sotto api 24. Ci sono librerie di terze parti che implementano la stessa cosa sebbene funzionino
tyczj

1
Ho una piccola libreria che fa cose simili per le
API


3
@PEMapModder È possibile utilizzare le espressioni lambda e di metodo riferimenti usando il nuovo compilatore Jack mira Android nel lontano Gingerbread. Ciò che non puoi avere sotto SDK 24 sono metodi di interfaccia statici / predefiniti e API specifiche di Java 8 come l'API Stream.
Sartorius

Puoi utilizzare la classe StreamSupport in API 24
Özer Özcan

Risposte:


71

[risposta originale]

Non è possibile utilizzare flussi Java8 a livello API <24.

Tuttavia, ci sono alcune librerie che eseguono il backport di alcune delle funzionalità del flusso

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

https://github.com/konmik/solid

https://sourceforge.net/projects/streamsupport/ (menzionato da @sartorius nel commento)

[aggiornamento k3b 23/05/2019]

https://github.com/retrostreams/android-retrostreams è uno spinoff di streamsupport che sfrutta la capacità della toolchain di Android Studio 3.x D8 / desugar di utilizzare metodi statici e predefiniti dell'interfaccia oltre i limiti del file Jar. Ci sono anche collegamenti ad altri android-retroXXX cioè per CompletableFuture.

[aggiornamento aeracode 2020-07-24]

Buone notizie , ora possiamo utilizzare Java 8 Stream API e altro senza richiedere un livello API minimo .


9
Sebbene solide e Lightweight-Stream-API siano certamente opzioni preziose per la programmazione simile a Stream, IMHO nessuna di esse può essere considerata nemmeno in remoto un "backport" dell'API Java 8 Stream. L'unico progetto che conosco che può affermare di essere vicino nella sintassi e alla pari in termini di funzionalità ai flussi Java 8 è il supporto per lo streaming . Ad esempio, supporta anche flussi paralleli. Anche se potrebbe non essere così importante per gli sviluppatori Android.
Sartorius

IMO, Lightweight-Stream-API era la più bella su Android grazie al supporto Gradle e l'aggiunta di extra come "select", "groupBy", ecc . Github.com/aNNiMON/Lightweight-Stream-API#additional-operators .
LordParsley

2
@LordParsley streamsupport ha anche il supporto Gradle. Per quanto riguarda gli extra, sì, è vero. A quanto ho capito, l'estensione / la deviazione dall'API ufficiale di Java 8 non è mai stato un obiettivo di progettazione del supporto di streaming.
Sartorius

3
@Sartorius ha ragione - Consiglio di controllare il mirror di Github per i dettagli sull'utilizzo e il riferimento Gradle github.com/streamsupport/streamsupport
LordParsley

Ho letto che in generale i Java Stream sono più lenti delle raccolte. stackoverflow.com/questions/22658322/… E questi backport?
Shikhar Shrivastav

12

Dalla versione 8.2 di DexGuard è possibile utilizzare l'API Java 8 stream anche su dispositivi Android <livello API 24. Per fare ciò, è necessario includere la libreria di supporto stream e DexGuard tradurrà tutte le chiamate API Java 8 stream nel biblioteca. Non è necessaria alcuna gestione aggiuntiva e gli sviluppatori possono semplicemente codificare utilizzando l'API Java 8 stream fornita. Anche le dipendenze vengono tradotte automaticamente, quindi è possibile utilizzare librerie con funzionalità Java 8 anche per lo sviluppo Android.

Questa funzionalità sarà inclusa anche in ProGuard nel prossimo futuro, rimanete sintonizzati.

Modifica: Proguard 6.1.0 per il quale esiste già una versione beta supporta il backporting del flusso Java 8 e dell'API temporale.


non è una libreria ufficiale
user25

Non ho idea della libreria stessa, ma consiglierei di controllare la licenza della libreria prima dell'uso in un progetto commerciale. GNU General Public License, versione 2, con l'eccezione Classpath . Probabilmente uno strato deve confermare.
Michal Harakal

5
@MichalHarakal mi ci sono voluti un paio di secondi per rendermi conto che lo strato era in realtà un avvocato :)
superjos

6

Potrebbe essere un po 'tardi per la festa, ma ho appena visto che se lo usiamo java8.util.stream.StreamSupportpossiamo eseguire lo stesso approccio di programmazione funzionale e usarlo prima di Api 24. Ad esempio, tratto da web3j -

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

3
@AjahnCharles Dire alle persone di usare solo la lingua B quando la loro domanda riguarda la lingua A non è una buona risposta. Molti progetti sono ancora scritti in Java.
mkuech

2
@AjahnCharles Hai un buon punto su come attirare l'attenzione dei lettori sulla possibilità di prendere in considerazione modifiche all'ecosistema Android. Detto questo, la domanda riguarda una caratteristica specifica di Java che è ancora un linguaggio ufficialmente supportato per lo sviluppo Android. Cambiare, anche se "solo" ibrida la tua app, comporta un costo (curva di apprendimento, forse il loro team non lo supporta, ecc.) E ciò richiede un'immersione in molto più di quanto viene chiesto nella domanda. Ancora più importante, il commento non indica come Kotlin sia una soluzione, il che la rende più fuori contesto e meno utile.
mkuech

3
@AjahnCharles quando è chiaramente menzionato Java 8 Stream API, penso che la risposta dovrebbe essere anche in JAVA!
Abhriya Roy

2

Sì, lo è ! A partire da AGP 4.0.0 possiamo utilizzare Stream API e alcune altre API Java 8+ (ad esempio java.time)

Modifiche minime richieste al build.gradle della tua 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'
}

-1

Un'altra soluzione che mi piace usare è usare staticamente le estensioni di Kotlin su Collezioni dal codice Java, se il progetto ovviamente supporta entrambe :

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

Lo stesso vale per .map, .reduce, .first, ecc ...


-5

Crea un'interfaccia.

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

Crea un metodo di filtro.

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

Utilizzo del codice

    public static class model {
            public String Name;
        }
List<model> models = new ArrayList<>();
            ...
            List<model> filtermodels = Filter(models,p-> p.Name.equals("filter"));
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.