¿Es posible utilizar la API de Java 8 Stream en la API de Android <24?

89

He leído esta publicación aquí. Pero aún así no puedo ejecutar código que contenga características de API de Java 8 Stream como las siguientes en minSdkVersion <24.

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

Esto no se ejecuta debido al mensaje de error

La llamada requiere un nivel de API 24 (el mínimo actual es 15): java.util.Collection # stream

Entonces, ¿alguien conoce una solución?

ilimitado101
fuente
3
no, no puede usar la secuencia de Java debajo de la API 24. Hay bibliotecas de terceros que implementan lo mismo aunque eso funciona
tyczj
1
Tengo una pequeña biblioteca que hace cosas similares para apis inferiores: github.com/smaspe/FunctionalIterables
njzk2
2
Consulte stackoverflow.com/questions/39265004/… y stackoverflow.com/questions/39039566/… para preguntas similares (y respuestas).
Sartorius
3
@PEMapModder Usted puede usar expresiones lambda y referencias de métodos que utilizan el nuevo compilador Jack focalización Android ya en pan de jengibre. Lo que no puede tener debajo del SDK 24 son métodos de interfaz predeterminados / estáticos y API específicas de Java 8, como la API Stream.
Sartorius
Puede usar la clase StreamSupport bajo API 24
Özer Özcan

Respuestas:

69

[respuesta original]

No puede utilizar secuencias de Java8 en el nivel de API <24.

Sin embargo, hay algunas bibliotecas que respaldan algunas de las funciones de transmisión.

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

https://github.com/konmik/solid

https://sourceforge.net/projects/streamsupport/ (mencionado por @sartorius en el comentario)

[actualización k3b 2019-05-23]

https://github.com/retrostreams/android-retrostreams es un derivado de streamsupport que aprovecha la capacidad de Android Studio 3.x D8 / desugar toolchain para usar la interfaz por defecto y métodos estáticos a través de los límites de los archivos Jar. También hay enlaces a otros android-retroXXX, es decir, para CompletableFuture.

[actualización de aeracode 2020-07-24]

Buenas noticias , ahora podemos usar Java 8 Stream API y más sin requerir un nivel mínimo de API .

Robert Estivill
fuente
9
Si bien la sólida y Lightweight-Stream-API son ciertamente opciones valiosas para la programación tipo Stream, en mi humilde opinión, ninguna de ellas puede considerarse ni remotamente un "backport" de la API de Java 8 Stream. El único proyecto que conozco que puede afirmar que tiene una sintaxis similar y una funcionalidad similar a las transmisiones de Java 8 es la compatibilidad con transmisiones . Por ejemplo, también admite flujos paralelos. Aunque eso podría no ser tan importante para los desarrolladores de Android.
Sartorius
En mi opinión, Lightweight-Stream-API fue el mejor en Android debido a la compatibilidad con Gradle y extras adicionales como "select", "groupBy", etc. github.com/aNNiMON/Lightweight-Stream-API#additional-operators .
LordParsley
2
@LordParsley streamsupport también tiene soporte para Gradle. En cuanto a los extras, sí, eso es cierto. Según tengo entendido, extender / desviar la API oficial de Java 8 nunca ha sido un objetivo de diseño de streamsupport.
Sartorius
3
@Sartorius tiene razón: recomiendo consultar el espejo de Github para obtener detalles de uso y las referencias de Gradle github.com/streamsupport/streamsupport
LordParsley
He leído que, en general, los Java Streams son más lentos que las colecciones. stackoverflow.com/questions/22658322/… ¿Qué pasa con estos backports?
Shikhar Shrivastav
12

Desde la versión 8.2 de DexGuard , es posible usar la API de flujos de Java 8 también en dispositivos Android <API nivel 24. Para hacerlo, es necesario incluir el soporte de flujo biblioteca y DexGuard se traducirá todos Java 8 flujo de llamadas a la API a la prevista biblioteca. No se necesita manejo adicional, y los desarrolladores pueden simplemente codificar usando la API de flujos de Java 8 proporcionada. Las dependencias también se traducen automáticamente, por lo que es posible utilizar bibliotecas con características de Java 8 también para el desarrollo de Android.

Esta función también se incluirá en ProGuard en un futuro cercano, estad atentos.

Editar: Proguard 6.1.0 para el que ya existe una versión beta es compatible con el backporting de Java 8 stream y time API.

T. Neidhart
fuente
no es la biblioteca oficial
usuario25
Realmente no tengo idea de la biblioteca en sí, pero recomendaría verificar la licencia de la biblioteca antes de usarla en un proyecto comercial. Licencia pública general GNU, versión 2, con la excepción Classpath . Probablemente una capa tenga que confirmar.
Michal Harakal
5
@MichalHarakal me tomó un par de segundos darme cuenta de que la capa era en realidad un abogado :)
superjos
6

java8.util.stream.StreamSupportPuede que llegue un poco tarde a la fiesta, pero acabo de ver que si lo usamos , podemos ejecutar el mismo enfoque de programación funcional y usarlo antes de Api 24. Por ejemplo, tomado de web3j -

StreamSupport.stream(transactionReceipt.getLogs())
            .map(log -> extractEventParameters(event, log))
            .filter(Objects::nonNull)
            .collect(Collectors.toList());
Abhriya Roy
fuente
3
@AjahnCharles Decirle a la gente que solo use el idioma B cuando su pregunta es sobre el idioma A no es una buena respuesta. Muchos proyectos todavía están escritos en Java.
mkuech
2
@AjahnCharles usted hace un punto de dibujar la atención del lector a la buena posiblemente teniendo en cuenta los cambios en el ecosistema Android. Dicho esto, la pregunta es sobre una característica específica de Java que todavía es un lenguaje oficialmente compatible para el desarrollo de Android. Cambiar, incluso si "solo" hibrida su aplicación, conlleva un costo (curva de aprendizaje, tal vez su equipo no lo admita, etc.) y eso requiere sumergirse en mucho más de lo que se pregunta en la pregunta. Más importante aún, el comentario no aborda cómo Kotlin es una solución, lo que lo hace más fuera de contexto y menos útil.
mkuech
3
@AjahnCharles cuando se menciona claramente Java 8 Stream API, creo que la respuesta también debería estar en JAVA.
Abhriya Roy
1

¡Sí lo es ! A partir de AGP 4.0.0 podemos usar Stream API y algunas otras API de Java 8+ (por ejemplo java.time)

Cambios mínimos requeridos en build.gradle de su aplicación :

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
fuente
-1

Otra solución que me gusta usar es usar estáticamente las extensiones de Kotlin sobre las colecciones del código Java, si el proyecto admite ambos, por supuesto :

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

Lo mismo para .map, .reduce, .first, etc ...

y.allam
fuente
-6

Cree una interfaz.

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

Cree un método de 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;
        }
    }

Usando código

    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
fuente