[英]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.