向来有学了CPlusPlus之后学Java非常快这么一说,但是这个“快”我觉得体现在两个方面:一是语言基础,二是语言思想。前者来说几乎所有的语言都差不多;后者来说主要是面向对象思想,而Java给我的感觉会更强烈。所以其实就是入门上手快,由于Java类库比较丰富,所以粗通语言不一定能看明白别人的代码。这篇文章主要是作为笔记吧,毕竟几乎都是翻译文档的。
Package java.util.stream
为数据元素流提供一系列函数风格的操作。主要包括接口BaseStream、Collector、DoubleStream、IntStream、LongStream、Stream;类Collectors、StreamSupport。其中BaseStream是最基础的接口,表示支持顺序或者并行聚合操作的元素序列。 有诸多获取流的方式,例如:从集合的stream()或者parallelStream()方法获取;从数组Array.stream(Object[])获取;从stream类的静态方法中获取,如Stream.of(Objectp[)以及IntStream.range(int,int)等等。
流操作可以分为中间操作和终端操作,这些操作构成了流管线。一条流管线包括产生流的源头(集合、数组、生成器函数、I/O管道等)、一系列中间操作(过滤、映射等)和一个终端操作(遍历等)。中间操作返回新的流。
流支持串行执行(默认)和并行执行(显式指出)。例如,集合具有方法Collection.stream()和Collection.parallelStream(),分别产生串行序列和并行流。其它承载流的方法,如IntStream.range(int,int)返回顺序流,但可以进一步调用parallel()方法实现并行化。isParallel()方法可以用来确定流的执行方式。流的串行还是并行不应该改变计算的结果。
流支持各种数据源可能并行的聚合操作,甚至包括ArrayList等非线程安全的集合。但在这个过程中,不能对数据源有干扰,姑且可以理解为在这个过程中不修改源数据。
Package java.util.stream.IntStream
public interface IntStream extends BaseStream<Integer, IntStream>;//原型声明
static IntStream range(int startInclusive, int endExclusive);//返回元素值在区间[startInclusive,endExclusive)内的有序序列,步长为1
void forEach(IntConsumer action);//遍历为流中的每个元素执行相应action
IntStream parallel();//返回并行的等效流
<U>Stream<U>mapToObj(IntFunction<?extends U>mapper);//返回一个对象流,该流是将给定函数应用到当前流中元素后的结果
DoubleStream mapToDouble(IntToDoubleFunction mapper);//返回一个DoubleStream,该流是将给定函数应用到当前流中元素后的结果
int[] toArray();//返回一个包含当前流元素的数组
import java.util.stream.IntStream;
class A{
double compute(double x,double y){return x+y;}
}
public StreamTest{
int mum = 0;
public static void main(String[]args){
IntStream m_stream1 = IntStream.range(0,10);
m_stream1.forEach(System.out::print);//输出0123456789
System.out.println();
IntStream m_stream2 = IntStream.range(0,10).parallel();
m_stream2.forEach(System.out::print);//一个可能的输出:6528941370
//the code that i need to understand is similar to the following
List<A>list = new ArrayList<A>();
list.add(new A());
list.add(new A());
Float [][]sl=IntStream.range(0, 9).parallel().mapToObj(y->
IntStream.range(0, 9).parallel().mapToObj(x->
(float)list.stream().mapToDouble(p->{
mum++;
return p.compute(1.0*y,1.0*x);
}).sum()
).toArray(Float[]::new)
).toArray(Float[][]::new);
}
}
上述代码的执行逻辑大概是这样子:外层IntStream.range(0,9)产生一个有序流,将该流并行化后,调用mapToObj()对该流中的每个元素执行相应函数,即转到内层。内层IntStream.range(0,9).parallel().mapToObj()也对流中的每个元素执行相应函数,就是计算一个求和结果,该结果作为数组元素值。
并行后我源程序执行九百多万次大概减少到八百万的样子,可能在更复杂的程序中会节省很多性能吧。
一直对CPlusPlus中流的概念不太清晰,这会儿倒是有些感觉了。