簡體   English   中英

Java 8中的Lambda表達式

[英]Lambda expressions in Java 8

我想使用lambda表達式而不是for循環生成數字列表。

所以,假設我要生成一個100以下的所有三角數列表。三角數是遵循以下公式的數字:(n * n + n)/ 2

這樣做的最佳方式是什么? 目前我有這個:

    Stream.iterate(1, n -> n + 1).limit(100)
            .map(n -> (n * n + n) / 2)
            .filter(a -> a < 100)
            .map(a -> a + "")
            .collect(Collectors.joining(", ", "Numbers: ", "."));

但這似乎不必要地計算量太多了。 我迭代n超過1到100(因為我假設我不知道n的最大值是什么),然后我映射該列表的三角數函數然后我檢查哪些數字在100以下。是否有更有效的方法這樣做? 另外:我可以僅使用Stream的迭代函數生成三角形數字而不是使用迭代,限制然后映射嗎?

編輯:所以這里的要點是: 一旦三角形數字之一超過100,如何計算traingle數字? 通常我會這樣寫:

ArrayList<Integer> triangles = new ArrayList<>(); 
for (int n=1;true;n++) {
    int num = (n*n+n)/2;

    if (num>100) break;

    triangles.add(num);
}

一旦三角形數超過100就停止,這是非常有效的; 如何在lambda表達式中保留這種效率?

一般情況下,您正在尋找的是需要的時間。 不幸的是,它在Java 8流中沒有默認實現。 查看有關take-while問題

如果您要做的就是將給定的序列轉換為三角形(如您所述),這樣做會更簡單。

List<Integer> l = IntStream.rangeClosed(1, 100)
            .mapToObj(n -> (n*n + n) / 2)
            .collect(Collectors.toList());

原始流包裝器需要一個額外的步驟來向上轉換為對象,因此mapToObj方法。

如果你打算在達到100時停止過濾,我能想到的最簡單的方法就是

    IntFunction<Integer> calc =n -> (n*n+n) / 2; 
    List<Integer> l = IntStream.rangeClosed(1, 100)
            .filter(n -> calc.apply(n) < 100)
            .mapToObj(calc)
            .collect(Collectors.toList());

根據您的問題的變化,我認為這也是非常重要的指出。 如果你想鏡像你以前做的事情,那將是這樣的:

    List<Integer> results = new ArrayList<>(100);
    IntStream.rangeClosed(1, 100).forEach(i -> {
        int tri =calc.apply(i);
        if(tri < 100) {
            results.add(tri);
        }
    });

值得指出的是,流不一定是有序的(盡管默認實現遵循迭代器)。 如果將其轉換為並行流,您將看到差異(以及流的功能)。 你不能打破執行,因為那時你假定有一定數量的處理順序。 通過提前過濾(以我的第二種形式),您將確保在最終計算之前最終只有13個條目的結果流。 將此並行選項作為注釋。

    List<Integer> l = IntStream.rangeClosed(1, 100).parallel()
            .filter(n -> calc.apply(n) < 100)
            .mapToObj(calc)
            .collect(Collectors.toList());

你會看到它們仍然是有序的,但它們的計算是在多個線程上完成的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM