Stream流粗解

Stream流粗解

  • 声明性——更简洁,更易读
  • 可复合——更灵活
  • 可并行——性能更好

案例传送门:Stream流使用案例

  • 通过对交易的各项业务查询熟悉流的使用
Map<Dish.Type, List<Dish>> dishesByType = menu.stream().collection(groupingBy(Dish::getType));

流简介

简短定义:从支持数据处理操作的源生成的元素序列。

  • 元素序列:类似于集合,流也提供了一个接口,可以访问特定元素类型的一组有序值。与集合不同,集合的主要目的是以特定的时间和空间复杂度存储和访问元素(如ArrayList和LinkedList)。流的主要目的在于表达计算。集合讲的是数据,流讲的是计算。
  • 源: 流会使用一个提供数据的源,如集合、数组或输入/输出资源。从有序集合生成流时会保留原有的顺序。由列表生成的流,其元素顺序与列表一致。
  • 数据处理操作:流的数据处理功能类似于数据库的操作,以及函数式编程语言的常用操作,如filter、map、reduce、find、match、sort等。流操作可以顺序执行,也可以并行执行
  • 流水线:很多流操作本身会返回一个流,所以多个操作就可以链起来,形成一个流水线。
  • 内部迭代:与使用迭代器显式迭代的集合不同,流的迭代操作是在背后进行的。

示例如下,结果为:[pork, beef, chicken]

List<String> threeHighCalorDishNames 
					= menu.stream() //源为menu,是一个列表,在Stream流案例中的Dish类可以看到定义
						  /**
						   * Stream<T> filter(Predicate<? super T> predicate),steam流可用的一个操作,接收一个Predicate接口对象
						   * boolean test(T t),Predicate函数式接口定义的抽象方法,签名为 T -> booean
						   * 经过filter操作(筛选卡路里高于300的)得到新流
						   */
						  .filter(d -> d.getCalories() > 300) 
						  /**
						   * <R> Stream<R> map(Function<? super T, ? extends R> mapper),steam流可用的一个操作,接收一个Function接口对象
						   * R apply(T t),Function函数式接口定义的抽象方法,签名为 T -> R
						   * 经过map操作(映射为菜名)得到新流
						   */
						  .map(Dish::getName)
						  /**
						   * Stream<T> limit(long maxSize),steam流可用的一个操作,接收一个long型整数
						   * 经过limit操作(只选择前三个)得到新流
						   */
						  .limit(3)
						  /**
						   * 返回一个list
						   */
						  .collect(Collectors.toList());

System.out.println(threeHighCalorDishNames);

流与集合

集合:是一个内存中的数据结构,它包含数据结构中目前所有的值——集合中的每个元素都得先算出来才能添加到集合中。

  • 可比喻为DVD,视频已经完全存储到了DVD中。

流:是在概念上固定的数据结构(不能添加或删除元素),其元素时按需计算的,就像一个延迟创建的集合:在按需的一步步操作完成后才创建集合。

  • 可比喻为在线流媒体,缓存一部分看一部分,按需操作。
  • 也可比喻为用浏览器进行互联网搜索,假设搜索到多条匹配项,而可以得到一个流仅展示10个,点击下一页可展示接下来的10个,每次请求都是10个。

只能遍历一次

和迭代器类似,流只能遍历一次。遍历完成后,就称这个流已经被消费掉了。如下代码:

List<String> title = Arrays.asList("Java8", "Lambda", "Steam");
Stream<String> s = title.stream();
/**
 * Stream: void forEach(Consumer<? super T> action);
 * Consumer: void accept(T t);
 */
s.forEach(System.out::println);
s.forEach(System.out::println);

结果如图:只会遍历一次,第二次遍历就抛出了异常,说明流已经被消费掉了。
在这里插入图片描述

外部迭代与内部迭代

使用Collection接口需要用户去做迭代(比如for-each),这称为外部迭代。相反,Streams库使用内部迭代——它帮你把迭代做了,还把得到的流存在了某个地方,只需要给出函数说要干什么就可以了。如下分别是集合和流的代码,说明了这种区别。

  • 集合:用for-each循环外部迭代
List<String> names = new ArrayList<>();
for (Dish d : menu) { // 显示顺序迭代菜单列表
	names.add(d.getName()); // 提取名称并将其添加到累加器
}
  • 集合:用背后的迭代器做外部迭代
List<String> names = new ArrayList<>();
Iterator<Dish> iterator = menu.iterator();
while (iterator.hasNext()) {
    Dish d = iterator.next();
    names.add(d.getName());
}
  • 流:内部迭代
List<String> names = menu.stream()
                .map(Dish::getName) // 传递行为,用getName方法参数化map,提取菜名
                .collect(Collectors.toList());
集合:外部迭代,必须一个一个处理

你:“索菲亚,我们把玩具收起来吧。地上还有玩具吗?”
索菲亚:“有,球。”
你:“好,把球放进盒子里。还有吗?”
索菲亚:“有,娃娃。”
你:“好,把娃娃放进盒子里。还有吗?”

索菲亚:“没了,没有了。”
你:“好,我们收完了。”

流:内部迭代,可以很好的并行处理,索菲亚可以一手球一手娃娃

你:“索菲亚,把地上的玩具都收起来。”
索菲亚:“好的。”

流操作

  • 中间操作:从源获取流开始,可以进行多个类似于filter、sorted方法等中间操作,这些操作的结果还是流。
  • 终端操作:经过一系列的中间操作后,最后使用一个终端方法,从流的流水线生成结果,该结果为其他非流的值,如List、Integer等,甚至可以是void。
  • 使用流:
    • 一个数据源(如集合)来执行一个查询;
    • 一个中间操作链,形成一条流的流水线;
    • 一个终端操作,执行流水线,并能生成结果。

使用流,具体案例点此

筛选和切片
filter

Stream接口支持filter方法,该操作接受一个谓词作为参数,并返回一个包含符合谓词的元素的流。

List<Dish> vegetarianMenu = menu.stream()
								.filter(Dish::isVegetarian)
								.collect(toList());
distinct

Stream接口支持distinct方法,该操作会返回一个元素各异的流。

List<Integer> numbers = Arrays.asList(1,2,1,3,3,2,4);
numbers.stream()
	   .filter(i -> i % 2 == 0)
	   .distinct()
	   .forEach(System.out::println);
limit

Stream接口支持limit(n)方法,该方法返回一个不超过给定长度的流。

List<Dish> dishes = menu.stream()
						.filter(d -> d.getCalories() > 300)
						.limit(3)
						.collect(toList());
skip

Stream接口支持skip(n)方法,与limit方法互补,返回一个丢掉前n元素的流。

List<Dish> dishes = menu.stream()
						.filter(d -> d.getCalories() > 300)	
						.skip(2)
						.collect(toList());	
映射

Stream接口支持map和flatMap方法,接收一个函数作为参数,这个函数会作用到流的每个元素,并将其映射成一个新的元素。

map
flatMap
查找和匹配
anyMatch
allMatch
findAny
findFirst
规约
reduce
Volume=[80,80,7]; PPV=2; % s = RandStream('dsfmt19937'); VolumePosiX=(rand([round(prod(Volume)*PPV),1])-1/2)*Volume(1); VolumePosiY=(rand([round(prod(Volume)*PPV),1])-1/2)*Volume(2); VolumePosiZ=(rand([round(prod(Volume)*PPV),1])-1/2)*Volume(3); VolumeIntense=abs((randn([round(prod(Volume)*PPV),1]))*0.2+1); % VolumeRadius=abs((rand([round(prod(Volume)*PPV),1])-0.5)*0.2+1)*0.75; VolumeRadius=abs((rand([round(prod(Volume)*PPV),1])-0.5)*0.0+1)*0.75; VolumeData.VolumePosiX=VolumePosiX; VolumeData.VolumePosiY=VolumePosiY; VolumeData.VolumePosiZ=VolumePosiZ; VolumeData.VolumeIntense=VolumeIntense; VolumeData.VolumeRadius=VolumeRadius; VolumeData.Volume=Volume; 2. 相机参数 旋转矩阵、平移向量、相机内参 Cam1.focal=116; Cam1.pixsize=10; % um Cam1.Resol=[1024,1024]; Cam1.ViewCenter=[0,0,0]; Cam1.Position=[0,200,500]; Cam1.RotationAngle=0; Cam2.focal=116; Cam2.pixsize=10; % um Cam2.Resol=[1024,1024]; Cam2.ViewCenter=[0,0,0]; Cam2.Position=[0,-200,500]; Cam2.RotationAngle=0; Cam3.focal=116; Cam3.pixsize=10; % um Cam3.Resol=[1024,1024]; Cam3.ViewCenter=[0,0,0]; Cam3.Position=[200,0,500]; Cam3.RotationAngle=0; Cam4.focal=116; Cam4.pixsize=10; % um Cam4.Resol=[1024,1024]; Cam4.ViewCenter=[0,0,0]; Cam4.Position=[-200,0,500]; Cam4.RotationAngle=0; figure,hold on myPlot3DBox(Volume,[0,0,0],'g-') myPlot3DArrow([0,0,0],[1,0,0]*30,10,'m') myPlot3DArrow([0,0,0],[0,1,0]*30,10,'m') myPlot3DArrow([0,0,0],[0,0,1]*30,10,'m') myShowCamera(Cam1) myShowCamera(Cam2) myShowCamera(Cam3) myShowCamera(Cam4) box on grid on 3. 相机上的粒子图像 Image(:,:,1)=myRecordImage(VolumeData,Cam1); Image(:,:,2)=myRecordImage(VolumeData,Cam2); Image(:,:,3)=myRecordImage(VolumeData,Cam3); Image(:,:,4)=myRecordImage(VolumeData,Cam4); figure, for ii=1:4 subplot(2,2,ii),imshow(Image(:,:,ii),[0,2]) end 4. 标定函数 MergeMF1{1,1}=myGetMFData(VolumeData,Cam1); MergeMF1{2,1}=myGetMFData(VolumeData,Cam2); MergeMF1{3,1}=myGetMFData(VolumeData,Cam3); MergeMF1{4,1}=myGetMFData(VolumeData,Cam4); 5. 重构 ParaSet.CamNum=4; ParaSet.iternum=6; ParaSet.ppp=0.06; ParaSet.InitFlag='uniform'; ParaSet.RecMethod='SF-MART'; ParaSet.resizelevel=5; ParaSet.VolXgrid=[-17.5:0.05:17.5]; ParaSet.VolYgrid=[-17.5:0.05:17.5]; ParaSet.VolZgrid=[-3.5:0.05:3.5]; ParaSet.zerothre=0.02; % ParaSet.wight_r=1; % sqrt(1)/2,sqrt(2)/2,sqrt(pi)/pi ParaSet.wight_r=0.6; ParaSet.EnhanceTime=1; Image(:,:,1)=myRecordImage(VolumeData,Cam1); Image(:,:,2)=myRecordImage(VolumeData,Cam2); Image(:,:,3)=myRecordImage(VolumeData,Cam3); Image(:,:,4)=myRecordImage(VolumeData,Cam4); [~, VolumeSpace]=TOMOREC_MLOS_MART_CONV_CPU2025(MergeMF1,Image,ParaSet); % VolumeData1=myMoveParticles(VolumeData,'Parallel flow',0.5); % Vortex ring VolumeData1=myMoveParticles(VolumeData,'Vortex ring',2.9*0.05); Image1(:,:,1)=myRecordImage(VolumeData1,Cam1); Image1(:,:,2)=myRecordImage(VolumeData1,Cam2); Image1(:,:,3)=myRecordImage(VolumeData1,Cam3); Image1(:,:,4)=myRecordImage(VolumeData1,Cam4); [~, VolumeSpace1]=TOMOREC_MLOS_MART_CONV_CPU2025(MergeMF1,Image1,ParaSet); 6. 互相关计算 Para.Overlap=[32,24,16,16];Para.Window=[64,48,32,32];Para.Expand=[12,8,4,2]; Para.Shift=[0,0,0,0];Para.IsNormalized=[1,1,1,1];Para.IsGPU=[0,0,0,0]; [xmesh,ymesh,zmesh,U,V,W,Corr]=myMultiPassAll3D_03(VolumeSpace,VolumeSpace1,Para);你好,这是我的虚拟3dtomoPIV平台代码,会生成42×42×7的速度场U,V,W,我想要你查询相关资料,然后给出生成各种图像的建议以及相应代码,我需要来做成论文与发表sci文章,请给出建议与代码。
最新发布
06-20
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值