導(dǎo)讀:
筆者使用的是小米筆記本 1.99 GHz 四核Intel Core i7店乐,本文對(duì)比了幾種方法求素?cái)?shù)耗時(shí)呻袭。這幾種方法分別是:傳統(tǒng)的for方法,java8 stream流廉侧,parallel stream篓足。結(jié)果表明stream性能通常差一點(diǎn),但是寫法更簡潔栈拖,世間安得雙全法连舍,不負(fù)如來不負(fù)卿?parallel stream辱魁,充分利用多核性能吧Q糖啤!染簇!
Stream
Java8 增加了重要的特性是Stream流参滴。stream的使用可以將代碼中大量的for循環(huán)變?yōu)橐幌盗泻啙嵉母唠A函數(shù)操作。
1.8以前要收集一個(gè)業(yè)務(wù)對(duì)象DTO的列表中的某個(gè)業(yè)務(wù)對(duì)象字段锻弓,我們需要這樣寫:
List<Integer> list = new ArrayList<>(timeConsumptionList.size());
for (TimeConsumption timeConsumption : timeConsumptionList) {
list.add(timeConsumption.getN());
}
現(xiàn)在可以這樣寫了
List<Integer> nList = timeConsumptionList.stream()
.map(TimeConsumption::getN)
.collect(Collectors.toList());
正題
好了砾赔。不說廢話了,切入正題青灼,上比較代碼暴心。
package lambdasinaction.chap6;
import com.google.gson.Gson;
import lombok.Data;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.IntStream;
/**
* @author chuanyi@88.com
* @date 2020/8/14
* @Description
*/
public class NotePad {
public static void main(String[] args) {
//輸出(2 -> n)的 素?cái)?shù)
int n = 10;
List<TimeConsumption> timeConsumptionList = new ArrayList<>();
for (int i = 0; i < 6; i++) {
TimeConsumption timeConsumption = new TimeConsumption();
timeConsumption.setN(n);
Time time = new Time();
findPrimeByTraditional(n,time);
findPrimeByStream(n,time);
findPrimeByParallelStream(n,time);
timeConsumption.setTime(time);
timeConsumptionList.add(timeConsumption);
n *= 10;
}
System.out.println(new Gson().toJson(timeConsumptionList));
}
@Data
public static class TimeConsumption implements Serializable {
private int n;
private Time time;
}
@Data
public static class Time implements Serializable{
private int streamTime;
private int parallelStreamTime;
private int traversalTime;
}
private static void findPrimeByTraditional(int n,Time time) {
long start2 = System.currentTimeMillis();
findPrimeNumbers(n);
int cost = (int) (System.currentTimeMillis() - start2);
time.setTraversalTime(cost);
System.out.println("cost by traditional method:" + cost + " ms");
}
private static void findPrimeByParallelStream(int n,Time time) {
long start = System.currentTimeMillis();
IntStream.iterate(2, i -> i < n, i -> i + 1).parallel().filter(NotePad::isPrime).forEach(System.out::println);
int cost = (int) (System.currentTimeMillis() - start);
time.setParallelStreamTime(cost);
System.out.println("parallel stream cost :" + cost + " ms");
}
private static void findPrimeByStream(int n,Time time) {
long start = System.currentTimeMillis();
IntStream.iterate(2, i -> i < n, i -> i + 1).filter(NotePad::isPrime).forEach(System.out::println);
int cost = (int) (System.currentTimeMillis() - start);
time.setStreamTime(cost);
System.out.println("stream cost :" + cost + " ms");
}
private static void findPrimeNumbers(int i) {
for (int j = 2; j < i; j++) {
if (isAPrime(j)) {
System.out.println(j);
}
}
}
public static boolean isAPrime(int n) {
int sqrt = (int) Math.sqrt(n);
for (int i = 2; i <= sqrt; i++) {
if (n % i == 0) {
return false;
}
}
return true;
}
public static boolean isPrime(int n) {
int sqrt = (int) Math.sqrt(n);
return IntStream.iterate(2, i -> i <= sqrt, i -> i + 1).parallel().noneMatch(i -> n % i == 0);
}
}
更直觀的折線圖
綜述
傳統(tǒng)的for方法性能還是十分給力的,但是代碼太長了檀夹,人生苦短炸渡,效果和工作量一定要權(quán)衡好蚌堵,差不多的表現(xiàn)情況下,如果對(duì)實(shí)際業(yè)務(wù)無明顯影響督赤,當(dāng)然選擇更簡潔的方法够挂。stream性能太差了孽糖,在數(shù)據(jù)較少的情況下和for的差距不值一提毅贮,但是數(shù)據(jù)量上來以后滩褥,就差太多了瑰煎,小老弟,你咋這么不給力呢魄健。相比于不爭氣的stream沽瘦,parallel stream表現(xiàn)還是相當(dāng)不錯(cuò)的析恋,而且還保留了stream的簡潔性助隧,正所謂青出于藍(lán)而勝于藍(lán)喇颁。但是在大規(guī)模數(shù)據(jù)面前,和最原始的for也還有一些差距蔫浆。但是日常使用中如果沒有這么大的數(shù)據(jù)量使用stream就可以了瓦盛。
后記
其實(shí)求素?cái)?shù)這里不用每次都求出來,可以求一次最大范圍的素?cái)?shù)挠唆,保留下來用作取模的除數(shù)玄组,這樣就能大大加快計(jì)算了俄讹。周末愉快~~