Java 8 里面的stream 有串行流和并行流之分。
说高级的stream就是那个并行流。下面是那个并行流的简单实现。只要是继承Collection类的都可以这么用。
并行流和串行流的介绍
为了适应目前多核机器的时代,提高系统CPU、内存的利用率,在jdk1.8新的stream包中针对集合的操作也提供了并行操作流和串行操作流。并行流就是把内容切割成多个数据块,并且使用多个线程分别处理每个数据块的内容。Stream api中声明可以通过parallel()与sequential()方法在并行流和串行流之间进行切换。
jdk1.8并行流使用的是fork/join框架进行并行操作
list.stream().parallel()
list.parallelStream()
public class Performance{
public static void main(String[] args) {
List list = getLoopList();
normalBeforeLoop(list);
normalAfterLoop(list);
notNormalAfterLoop(list);
}
private static void notNormalAfterLoop(List list) {
long a = System.currentTimeMillis();
list.stream().parallel().forEach(System.out::print);
System.out.println(" list.stream().parallel().forEach 执行耗时 : " + (System.currentTimeMillis() - a) / 1000f + " 秒 ");
}
private static void normalAfterLoop(List list) {
long a = System.currentTimeMillis();
list.stream().forEach(System.out::print);
System.out.println(" list.stream().forEach 执行耗时 : " + (System.currentTimeMillis() - a) / 1000f + " 秒 ");
a = System.currentTimeMillis();
list.forEach(System.out::print);
System.out.println(" list.forEach 执行耗时 : " + (System.currentTimeMillis() - a) / 1000f + " 秒 ");
}
private static void normalBeforeLoop(List list) {
long a = System.currentTimeMillis();
for (String s : list) {
System.out.print(s);
}
System.out.println(" for each 执行耗时 : " + (System.currentTimeMillis() - a) / 1000f + " 秒 ");
}
private static List getLoopList() {
List list = Lists.newArrayList();
for (int i = 0; i
list.add("item " + i);
}
return list;
}
运行结果:
可以看到java8的lambda的循环和java7的循环效率差不多,并行和串行的流的差别,可以看出并行的流,在循环的时候,就不是 1 - 9999 挨着输出。而是,看多核的心情。
串行并行比较:
public class Performance {
public static void main(String[] args){
int size = 5000000;
List uuisList = new ArrayList<>(size);
System.out.println("开始生成 = " + new Date());
//生成500万个uuid
for (int i = 0; i
uuisList.add(UUID.randomUUID().toString());
}
System.out.println("生成结束 = " + new Date());
System.out.println("开始串行排序");
long startTime = System.nanoTime();//纳秒,更为精确
uuisList.stream().sorted().count();//串行排序
long endTime = System.nanoTime();//纳秒,更为精确
long distanceTime = TimeUnit.NANOSECONDS.toMillis(endTime - startTime);
System.out.println("结束串行排序 耗时为 " + distanceTime);
System.out.println("开始并行排序");
long startTime1 = System.nanoTime();//纳秒,更为精确
uuisList.parallelStream().sorted().count();//并行排序
long endTime1 = System.nanoTime();//纳秒,更为精确
long distanceTime1 = TimeUnit.NANOSECONDS.toMillis(endTime1 - startTime1);
System.out.println("结束并行排序 耗时为 " + distanceTime1);
}
System.out::print 与 System.out.print的区别:
System.out::print :是方法引用
方法引用是当你想把一个方法当作一个“函数指针”传给别的方法用时有用的。
例如说,我有个ArrayList想把里面每个元素都打印出来,每个元素一行。
那么Java 8之前会这样写:
for (ElementType e : list) {
System.out.println(e);
}
从Java 8开始,使用ArrayList的新API加上lambda表达式,我们可以这样写:
list.forEach(e -> System.out.println(e));
而这里的lambda表达式的内容其实只不过就是把参数传给了println()方法,而没
有做任何别的事情,所以可以进一步简写为:
list.forEach(System.out::println);
重点:
System.out是一个PrintStream实例的引用;System.out::println 是对一个实例方法的引用
该引用同时指定了对实例(System.out)的引用以及对方法(PrintStream::println)的引用
System.out::println 不是 System.out.println 的等价物;前者是一个方法引用表达式,而后者不能单独作为一个表达式,而必须在后面跟上由圆括号包围的参数列表来构成方法调用表达式。
System.out::println 可以看作 lambda表达式 e -> System.out.println(e) 的缩写形式。