Apakah mungkin untuk menggunakan Java 8 Stream API di Android API <24?

89

Saya telah membaca posting ini di sini. Tapi tetap saja saya tidak bisa menjalankan kode yang berisi fitur Java 8 Stream API seperti berikut di minSdkVersion <24.

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

Ini tidak berjalan karena pesan kesalahan

Panggilan memerlukan API level 24 (minimum saat ini 15): java.util.Collection # stream

Jadi, apakah seseorang tahu solusinya?

tidak terbatas101
sumber
3
tidak, Anda tidak dapat menggunakan aliran java di bawah api 24. ada pustaka pihak ketiga yang menerapkan hal yang sama meskipun berfungsi
tyczj
1
Saya memiliki perpustakaan kecil yang melakukan hal serupa untuk api
njzk2
2
Lihat stackoverflow.com/questions/39265004/… dan stackoverflow.com/questions/39039566/… untuk pertanyaan (dan jawaban) serupa.
Sartorius
3
@PEMapModder Anda dapat menggunakan ekspresi lambda dan referensi metode menggunakan compiler Jack baru yang menargetkan Android sejauh Gingerbread. Yang tidak dapat Anda miliki di bawah SDK 24 adalah metode antarmuka default / statis dan API khusus Java 8 seperti API Stream.
Sartorius
Anda dapat menggunakan kelas StreamSupport di bawah API 24
Özer Özcan

Jawaban:

71

[jawaban asli]

Anda tidak dapat menggunakan aliran Java8 pada API level <24.

Namun, ada beberapa pustaka yang mendukung beberapa fungsionalitas aliran

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

https://github.com/konmik/solid

https://sourceforge.net/projects/streamsupport/ (disebutkan oleh @sartorius dalam komentar)

[perbarui k3b 2019-05-23]

https://github.com/retrostreams/android-retrostreams adalah spin-off dari streamsupport yang memanfaatkan kemampuan Android Studio 3.x D8 / desugar toolchain untuk menggunakan metode default & statis antarmuka melintasi batas file Jar. Ada juga tautan ke android-retroXXX lainnya yaitu untuk CompletableFuture.

[perbarui aeracode 24-07-2020]

Kabar baiknya , sekarang kita dapat menggunakan Java 8 Stream API dan lainnya tanpa memerlukan level API minimum .

Robert Estivill
sumber
9
Meskipun solid dan Lightweight-Stream-API tentunya merupakan pilihan yang berharga untuk pemrograman seperti Stream, IMHO tidak satupun dari mereka bahkan dapat dianggap sebagai "backport" dari Java 8 Stream API. Satu-satunya proyek yang saya tahu yang dapat mengklaim memiliki sintaks yang dekat dan setara dengan fungsionalitas untuk aliran Java 8 adalah dukungan streaming . Misalnya, ini juga mendukung aliran paralel. Padahal itu mungkin tidak begitu penting untuk pengembang Android.
Sartorius
IMO, Lightweight-Stream-API adalah yang terbaik di Android karena dukungan Gradle dan tambahan tambahan seperti "select", "groupBy", dll . Github.com/aNNiMON/Lightweight-Stream-API#additional-operators .
LordParsley
2
@LordParsley streamsupport juga memiliki dukungan Gradle. Adapun ekstra, ya itu benar. Seperti yang saya pahami, memperluas / mengalihkan dari Java 8 API resmi tidak pernah menjadi tujuan desain streamsupport.
Sartorius
3
@Sartorius benar - Saya sarankan untuk memeriksa cermin Github untuk detail penggunaan dan referensi Gradle github.com/streamsupport/streamsupport
LordParsley
Saya telah membaca bahwa secara umum Java Stream lebih lambat daripada koleksi. stackoverflow.com/questions/22658322/… Bagaimana dengan backport ini?
Shikhar Shrivastav
12

Sejak rilis 8.2 dari DexGuard adalah mungkin untuk menggunakan Java 8 stream API juga pada perangkat Android <API tingkat 24. Untuk melakukannya, salah satu kebutuhan untuk menyertakan streamsupport perpustakaan dan DexGuard akan menerjemahkan semua Java 8 aliran API panggilan ke yang disediakan Perpustakaan. Tidak diperlukan penanganan tambahan, dan pengembang cukup membuat kode menggunakan API aliran Java 8 yang disediakan. Dependensi juga diterjemahkan secara otomatis, sehingga memungkinkan untuk menggunakan pustaka dengan fitur Java 8 juga untuk pengembangan Android.

Fitur ini juga akan disertakan dalam ProGuard dalam waktu dekat, pantau terus.

Sunting: Proguard 6.1.0 yang sudah ada versi beta mendukung backporting aliran Java 8 dan API waktu.

T. Neidhart
sumber
ini bukan perpustakaan resmi
pengguna25
Saya benar-benar tidak tahu tentang perpustakaan itu sendiri, tetapi saya akan merekomendasikan untuk memeriksa lisensi perpustakaan sebelum digunakan dalam proyek komersial. Lisensi Publik Umum GNU, versi 2, dengan Pengecualian Jalur Kelas . Mungkin lapisan harus dikonfirmasi.
Michal Harakal
5
@MichalHarakal butuh waktu beberapa detik untuk menyadari bahwa lapisan itu sebenarnya adalah pengacara :)
superjos
6

Mungkin agak terlambat ke pesta, tapi saya hanya melihat bahwa Jika kita menggunakan java8.util.stream.StreamSupportmaka kita dapat menjalankan pendekatan pemrograman fungsional yang sama dan menggunakannya sebelum Api 24. Misalnya diambil dari web3j -

StreamSupport.stream(transactionReceipt.getLogs())
            .map(log -> extractEventParameters(event, log))
            .filter(Objects::nonNull)
            .collect(Collectors.toList());
Abhriya Roy
sumber
3
@AjahnCharles Menyuruh orang untuk hanya menggunakan bahasa B ketika pertanyaan mereka tentang bahasa A bukanlah jawaban yang bagus. Banyak proyek masih ditulis di Jawa.
mkuech
2
@AjahnCharles Anda membuat poin yang baik tentang menarik perhatian pembaca untuk kemungkinan mempertimbangkan perubahan pada ekosistem Android. Konon, pertanyaannya adalah tentang fitur khusus Java yang masih merupakan bahasa yang didukung secara resmi untuk pengembangan Android. Switching, bahkan jika "hanya" hibridisasi aplikasi Anda, membawa (kurva belajar, mungkin tim mereka tidak mendukung hal itu, dll) biaya dan yang membutuhkan menyelam ke dalam cara yang lebih dari apa yang diminta dalam pertanyaan. Lebih penting lagi, komentar tersebut tidak membahas bagaimana Kotlin adalah solusi, yang membuatnya lebih keluar dari konteks dan kurang berguna.
mkuech
3
@AjahnCharles kalau jelas disebutkan Java 8 Stream API, saya rasa, jawabannya juga harus di JAWA!
Abhriya Roy
2

Ya, benar ! Mulai dari AGP 4.0.0 kita dapat menggunakan Stream API dan beberapa Java 8+ API lainnya (mis. java.time)

Perubahan minimal yang diperlukan pada build.gradle aplikasi Anda :

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

Solusi lain yang suka saya gunakan adalah menggunakan ekstensi Kotlin secara statis di atas Koleksi dari kode Java, jika proyek tersebut mendukung keduanya tentu saja :

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

Sama untuk .map, .reduce, .first, ... dll

y.allam
sumber
-5

Buat Antarmuka.

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

Buat Metode Filter.

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

Menggunakan Kode

    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
sumber