Có thể sử dụng Java 8 Stream API trên Android API <24 không?


89

Tôi đã đọc bài này ở đây. Nhưng tôi vẫn không thể chạy mã chứa các tính năng Java 8 Stream API như sau trên minSdkVersion <24.

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

Điều này không chạy do thông báo lỗi

Cuộc gọi yêu cầu API cấp 24 (tối thiểu hiện tại là 15): java.util.Collection # stream

Vì vậy, có ai đó biết một giải pháp?


3
không bạn không thể sử dụng các dòng java dưới api 24. có thư viện của bên thứ 3 mà thực hiện điều tương tự mặc dù công việc đó
tyczj

1
Tôi có một thư viện nhỏ mà làm những việc tương tự cho apis thấp: github.com/smaspe/FunctionalIterables
njzk2

2
Xem stackoverflow.com/questions/39265004/…stackoverflow.com/questions/39039566/… để biết các câu hỏi tương tự (và câu trả lời).
Sartorius

3
@PEMapModder Bạn có thể sử dụng các biểu thức lambda và tham chiếu phương thức bằng cách sử dụng trình biên dịch Jack mới nhắm mục tiêu đến Android từ xa như Gingerbread. Những gì bạn không thể có bên dưới SDK 24 là các phương thức giao diện mặc định / tĩnh và các API cụ thể của Java 8 như API luồng.
Sartorius

Bạn có thể sử dụng lớp StreamSupport theo API 24
Özer Özcan

Câu trả lời:


69

[câu trả lời ban đầu]

Bạn không thể sử dụng các luồng Java8 ở cấp API <24.

Tuy nhiên, có một số thư viện hỗ trợ một số chức năng của luồng

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

https://github.com/konmik/solid

https://sourceforge.net/projects/streamsupport/ (được @sartorius đề cập trong bình luận)

[cập nhật k3b 2019-05-23]

https://github.com/retrostreams/android-retrostreams là một phần phụ từ streamsupport tận dụng khả năng của Android Studio 3.x D8 / desugar toolchain để sử dụng các phương thức mặc định và tĩnh của giao diện trên các ranh giới tệp Jar. Ngoài ra còn có các liên kết đến android-retroXXX khác, tức là cho CompletableFuture.

[cập nhật aeracode 2020-07-24]

Tin tốt là bây giờ chúng ta có thể sử dụng Java 8 Stream API và hơn thế nữa mà không yêu cầu cấp API tối thiểu .


9
Mặc dù solidLightweight-Stream-API chắc chắn là những lựa chọn có giá trị cho lập trình giống như Stream, IMHO không có cái nào trong số chúng thậm chí có thể được coi là "cổng hậu" của Java 8 Stream API từ xa. Dự án duy nhất mà tôi biết có thể khẳng định là gần giống về cú pháp và ngang bằng về chức năng với các luồng Java 8 là streamsupport . Ví dụ, nó cũng hỗ trợ các luồng song song. Mặc dù điều đó có thể không quá quan trọng đối với các nhà phát triển Android.
Sartorius

IMO, Lightweight-Stream-API là tốt nhất trên Android vì hỗ trợ Gradle và thêm các tính năng bổ sung như "select", "groupBy", v.v. github.com/aNNiMON/Lightweight-Stream-API#additional-operators .
LordParsley

2
@LordParsley streamsupport cũng có hỗ trợ Gradle. Đối với các tính năng bổ sung, đúng là như vậy. Theo tôi hiểu, việc mở rộng / chuyển hướng từ API Java 8 chính thức chưa bao giờ là mục tiêu thiết kế của streamsupport.
Sartorius

3
@Sartorius là đúng - Tôi khuyên bạn nên xem gương Github để biết chi tiết cách sử dụng và các Gradle refs github.com/streamsupport/streamsupport
LordParsley

Tôi đã đọc rằng nói chung Dòng Java chậm hơn các bộ sưu tập. stackoverflow.com/questions/22658322/… Còn những cổng lùi này thì sao?
Shikhar Shrivastav

12

Kể từ khi phát hành 8.2 của DexGuard nó có thể sử dụng Java 8 suối API cũng trên thiết bị Android <level API 24. Để làm như vậy, một trong những nhu cầu để bao gồm các streamsupport thư viện và DexGuard sẽ dịch tất cả Java 8 dòng cuộc gọi API để cung cấp thư viện. Không cần xử lý thêm và các nhà phát triển có thể viết mã đơn giản bằng cách sử dụng API Java 8 luồng được cung cấp. Các phần phụ thuộc cũng được dịch tự động, vì vậy có thể sử dụng các thư viện với các tính năng của Java 8 cũng để phát triển Android.

Tính năng này cũng sẽ được đưa vào ProGuard trong thời gian tới, hãy chú ý theo dõi.

Chỉnh sửa: Proguard 6.1.0 đã tồn tại một phiên bản beta hỗ trợ API thời gian và luồng Java 8 backporting.


nó không phải là thư viện chính thức
25

Tôi thực sự không biết gì về bản thân thư viện, nhưng tôi khuyên bạn nên kiểm tra giấy phép của thư viện trước khi sử dụng trong một dự án thương mại. Giấy phép Công cộng GNU, phiên bản 2, với Ngoại lệ Classpath . Có lẽ một lớp phải xác nhận.
Michal Harakal

5
@MichalHarakal, tôi phải mất vài giây để nhận ra rằng lớp đó thực sự là luật sư :)
superjos

6

Có thể đến bữa tiệc hơi muộn, nhưng tôi chỉ thấy rằng Nếu chúng ta sử dụng java8.util.stream.StreamSupportthì chúng ta có thể chạy cùng một phương pháp lập trình chức năng và sử dụng nó trước Api 24. Ví dụ: lấy từ web3j -

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

3
@AjahnCharles Bảo mọi người chỉ sử dụng ngôn ngữ B khi câu hỏi của họ về ngôn ngữ A không phải là một câu trả lời hay. Nhiều dự án vẫn được viết bằng Java.
mkuech

2
@AjahnCharles Bạn thực hiện một điểm tốt khi thu hút sự chú ý của người đọc để có thể xem xét các thay đổi đối với hệ sinh thái Android. Điều đó nói rằng, câu hỏi là về một tính năng cụ thể của Java vẫn là một ngôn ngữ được hỗ trợ chính thức để phát triển Android. Chuyển đổi, ngay cả khi "chỉ" kết hợp ứng dụng của bạn, mang lại một chi phí (đường cong học tập, có thể nhóm của họ không hỗ trợ nó, v.v.) và điều đó đòi hỏi phải tìm hiểu sâu hơn những gì đang được hỏi trong câu hỏi. Quan trọng hơn, nhận xét không đề cập đến việc Kotlin là giải pháp như thế nào , điều này khiến nó trở nên lạc lõng hơn và ít hữu ích hơn.
mkuech

3
@AjahnCharles khi nó được đề cập rõ ràng Java 8 Stream API, tôi cảm thấy, câu trả lời cũng nên có trong JAVA!
Abhriya Roy

1

Vâng, nó là ! Bắt đầu từ AGP 4.0.0, chúng ta có thể sử dụng Stream API và một số API Java 8+ khác (ví dụ java.time)

Các thay đổi bắt buộc tối thiểu đối với build.gradle của ứng dụng :

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

Một giải pháp khác mà tôi thích sử dụng là sử dụng tĩnh các phần mở rộng của Kotlin trên Bộ sưu tập từ mã Java, nếu dự án tất nhiên hỗ trợ cả hai :

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

Tương tự cho .map, .reduce, .first, ... vv


-6

Tạo giao diện.

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

Tạo một phương pháp lọc.

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

Sử dụng mã

    public static class model {
            public String Name;
        }
List<model> models = new ArrayList<>();
            ...
            List<model> filtermodels = Filter(models,p-> p.Name.equals("filter"));
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.