Чи можна використовувати API Java Stream API для Android API <24?


89

Я прочитав цю публікацію тут. Але все одно я не можу запустити код, що містить функції Java 8 Stream API, такі як наведені нижче на minSdkVersion <24.

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

Це не працює через повідомлення про помилку

Для виклику потрібен рівень API 24 (поточний хв - 15): java.util.Collection # stream

Тож хтось знає рішення?


3
ні, ви не можете використовувати потік Java нижче api 24. є сторонні бібліотеки, які реалізують одне і те ж, хоча це працює
tyczj

1
У мене є невелика бібліотека, яка робить подібні речі для нижнього apis: github.com/smaspe/FunctionalIterables
njzk2

2
Подивіться stackoverflow.com/questions/39265004/… та stackoverflow.com/questions/39039566/… для отримання подібних питань (і відповідей).
Sartorius

3
@PEMapModder Ви можете використовувати лямбда-вирази та посилання на методи, використовуючи новий компілятор Jack, націлений на Android ще до Gingerbread. Те, що ви не можете мати нижче SDK 24, - це методи за замовчуванням / статичний інтерфейс та специфічні API Java 8, такі як API потоку.
Sartorius

Ви можете використовувати клас StreamSupport за API 24
Özer Özcan

Відповіді:


69

[оригінальна відповідь]

Ви не можете використовувати потоки Java8 на рівні API <24.

Однак є деякі бібліотеки, які бекпортують деякі функції потоку

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 toolchain використовувати стандартні та статичні методи інтерфейсу через межі файлів Jar. Є також посилання на інші android-retroXXX, тобто на CompletableFuture.

[оновити аерокод 2020-07-24]

Хороші новини , тепер ми можемо використовувати Java 8 Stream API та інше, не вимагаючи мінімального рівня API .


9
Хоча надійні та полегшені-Stream-API , безумовно, є цінними варіантами для програмування, схожого на Stream, IMHO жоден з них не може навіть віддалено вважатись "backport" Java 8 Stream API. Єдиний проект, про який я знаю, який може стверджувати, що близький за синтаксисом та за рівнем функціональності до потоків Java 8 - це streamsupport . Наприклад, він також підтримує паралельні потоки. Хоча це може бути не так важливо для розробників Android.
Sartorius

IMO, Lightweight-Stream-API був найкращим на Android завдяки підтримці Gradle та додав додаткові функції, такі як "select", "groupBy" тощо. Github.com/aNNiMON/Lightweight-Stream-API#additional-operators .
LordParsley

2
@LordParsley streamsupport також має підтримку Gradle. Що стосується додаткових послуг, так це правда. Наскільки я розумію, розширення / переадресація від офіційного API Java 8 ніколи не було ціллю дизайну потокової підтримки.
Сарторіус,

3
@Sartorius має рацію - я рекомендую перевірити дзеркало Github для деталей використання та посилання Gradle github.com/streamsupport/streamsupport
LordParsley

Я читав, що загалом Java Streams працює повільніше, ніж колекції. stackoverflow.com/questions/22658322/… Що з цими бекпортами?
Шихар Шрівастав,

12

З випуском 8.2 DexGuard можна використовувати Java 8 потоки API також на Android пристроїв <рівня API 24. Для того , щоб зробити це, необхідно включити streamsupport бібліотеку і DexGuard переведе всі Java 8 потокових API виклики наданих бібліотека. Не потрібно додаткової обробки, і розробники можуть просто кодувати, використовуючи наданий API потоків Java 8. Залежності також перекладаються автоматично, тому можна використовувати бібліотеки з функціями Java 8 також для розробки Android.

Ця функція також буде включена в ProGuard найближчим часом, стежте за оновленнями.

Змінити: Proguard 6.1.0, для якої вже існує бета-версія, підтримує бекпортинг API Java 8 для потоку та часу.


це не офіційна бібліотека
user25,

Я не маю ідеї щодо самої бібліотеки, але я б рекомендував перевірити ліцензію бібліотеки перед використанням у комерційному проекті. Загальна публічна ліцензія GNU, версія 2, з винятком Classpath . Можливо, шар повинен підтвердити.
Міхал Харакал,

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 Навчання людей просто використовувати мову B, коли їхнє питання стосується мови A, не є гарною відповіддю. Багато проектів досі написані на Java.
mkuech

2
@AjahnCharles Ви гарно підкреслюєте, привертаючи увагу читачів до можливого розгляду змін в екосистемі Android. Тим не менш, питання стосується специфічної особливості Java, яка досі є офіційно підтримуваною мовою для розробки Android. Переключення, навіть якщо "лише" гібридизує ваш додаток, приносить витрати (крива навчання, можливо, їхня команда не підтримує це тощо), і це вимагає занурення в дорогу більше, ніж те, що задається у питанні. Що ще важливіше, коментар не стосується того, як Kotlin є рішенням, що робить його більш неконтекстним та менш корисним.
mkuech

3
@AjahnCharles, коли це чітко згадується Java 8 Stream API, я відчуваю, відповідь також повинна бути в JAVA!
Абрія Рой

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, якщо проект, звичайно, підтримує обидва :

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

Те ж саме для .map, .reduce, .first, ... і т.д.


-6

Створіть інтерфейс.

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"));
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.