当前位置: 首页 > news >正文

dw做网站背景图片设置铺平北京外包seo公司

dw做网站背景图片设置铺平,北京外包seo公司,网站浏览图片怎么做,杭州市网站建设文章目录 一、创建流二、中间操作和收集操作筛选 filter去重distinct截取跳过映射合并多个流是否匹配任一元素:anyMatch是否匹配所有元素:allMatch是否未匹配所有元素:noneMatch获取任一元素findAny获取第一个元素findFirst归约数值流的使用中…

文章目录

    • 一、创建流
    • 二、中间操作和收集操作
      • 筛选 filter
      • 去重distinct
      • 截取
      • 跳过
      • 映射
      • 合并多个流
      • 是否匹配任一元素:anyMatch
      • 是否匹配所有元素:allMatch
      • 是否未匹配所有元素:noneMatch
      • 获取任一元素findAny
      • 获取第一个元素findFirst
      • 归约
      • 数值流的使用
      • 中间操作和收集操作总结
      • Collector 收集
      • 归约
      • 一般性归约
      • 汇总
      • 分组
      • 多级分组
      • 转换类型
      • 数据分区
      • 并行流

在这里插入图片描述
stream在使用中主要分为以上图示阶段,接下来将详细展示java8中stream api的具体的实践使用案例。

一、创建流

在使用流之前,首先需要拥有一个数据源,并通过StreamAPI提供的一些方法获取该数据源的流对象。数据源可以有多种形式:

1. 集合

这种数据源较为常用,通过stream()方法即可获取流对象:

List<Person> list = new ArrayList<Person>(); 
Stream<Person> stream = list.stream();

2. 数组

通过Arrays类提供的静态函数stream()获取数组的流对象:

String[] names = {"chaimm","peter","john"};
Stream<String> stream = Arrays.stream(names);

3. 值

直接将几个值变成流对象:

Stream<String> stream = Stream.of("chaimm","peter","john");

4. 文件

try(Stream lines = Files.lines(Paths.get(“文件路径名”),Charset.defaultCharset())){//可对lines做一些操作
}catch(IOException e){
}

5. iterator

创建无限流

Stream.iterate(0, n -> n + 2).limit(10).forEach(System.out::println);

PS:Java7简化了IO操作,把打开IO操作放在try后的括号中即可省略关闭IO的代码。

二、中间操作和收集操作

筛选 filter

filter 函数接收一个Lambda表达式作为参数,该表达式返回boolean,在执行过程中,流将元素逐一输送给filter,并筛选出执行结果为true的元素。
如,筛选出所有学生:

List<Person> result = list.stream().filter(Person::isStudent).collect(toList());

去重distinct

去掉重复的结果:

List<Person> result = list.stream().distinct().collect(toList());

截取

截取流的前N个元素:

List<Person> result = list.stream().limit(3).collect(toList());

跳过

跳过流的前n个元素:

List<Person> result = list.stream().skip(3).collect(toList());

映射

对流中的每个元素执行一个函数,使得元素转换成另一种类型输出。流会将每一个元素输送给map函数,并执行map中的Lambda表达式,最后将执行结果存入一个新的流中。
如,获取每个人的姓名(实则是将Perosn类型转换成String类型):

List<Person> result = list.stream().map(Person::getName).collect(toList());

合并多个流

例:列出List中各不相同的单词,List集合如下:

List<String> list = new ArrayList<String>();
list.add("I am a boy");
list.add("I love the girl");
list.add("But the girl loves another girl");

思路如下:

首先将list变成流:

list.stream();

按空格分词:

list.stream().map(line->line.split(" "));

分完词之后,每个元素变成了一个String[]数组。

将每个 String[] 变成流:

list.stream().map(line->line.split(" ")).map(Arrays::stream)

此时一个大流里面包含了一个个小流,我们需要将这些小流合并成一个流。

将小流合并成一个大流:用 flatMap 替换刚才的 map

list.stream().map(line->line.split(" ")).flatMap(Arrays::stream)

去重

list.stream().map(line->line.split(" ")).flatMap(Arrays::stream).distinct().collect(toList());

是否匹配任一元素:anyMatch

anyMatch用于判断流中是否存在至少一个元素满足指定的条件,这个判断条件通过Lambda表达式传递给anyMatch,执行结果为boolean类型。
如,判断list中是否有学生:

boolean result = list.stream().anyMatch(Person::isStudent);

是否匹配所有元素:allMatch

allMatch用于判断流中的所有元素是否都满足指定条件,这个判断条件通过Lambda表达式传递给anyMatch,执行结果为boolean类型。
如,判断是否所有人都是学生:

boolean result = list.stream().allMatch(Person::isStudent);

是否未匹配所有元素:noneMatch

noneMatch与allMatch恰恰相反,它用于判断流中的所有元素是否都不满足指定条件:

boolean result = list.stream().noneMatch(Person::isStudent);

获取任一元素findAny

findAny能够从流中随便选一个元素出来,它返回一个Optional类型的元素。

Optional<Person> person = list.stream().findAny();

获取第一个元素findFirst

Optional<Person> person = list.stream().findFirst();

归约

归约是将集合中的所有元素经过指定运算,折叠成一个元素输出,如:求最值、平均数等,这些操作都是将一个集合的元素折叠成一个元素输出。

在流中,reduce函数能实现归约。
reduce函数接收两个参数:

  1. 初始值
  2. 进行归约操作的Lambda表达式

元素求和:自定义Lambda表达式实现求和

例:计算所有人的年龄总和

@Test
public void contextLoads() {List<Person> list = new ArrayList<>();list.add(new Person().setAge(20));list.add(new Person().setAge(25));int age = list.stream().map(Person::getAge).reduce(0, Integer::sum);System.out.println(age);
}
@Data
@Accessors(chain = true)
class Person {private int age;
}
  1. reduce的第一个参数表示初试值为0;
  2. reduce的第二个参数为需要进行的归约操作,它接收一个拥有两个参数的Lambda表达式,reduce会把流中的元素两两输给Lambda表达式,最后将计算出累加之和。

元素求和:使用Integer.sum函数求和

上面的方法中我们自己定义了Lambda表达式实现求和运算,如果当前流的元素为数值类型,那么可以使用Integer提供了sum函数代替自定义的Lambda表达式,如:

int age = list.stream().reduce(0, Integer::sum);

Integer类还提供了 minmax 等一系列数值操作,当流中元素为数值类型时可以直接使用。

数值流的使用

采用reduce进行数值操作会涉及到基本数值类型和引用数值类型之间的装箱、拆箱操作,因此效率较低。
当流操作为纯数值操作时,使用数值流能获得较高的效率。

将普通流转换成数值流

StreamAPI提供了三种数值流:IntStream、DoubleStream、LongStream,也提供了将普通流转换成数值流的三种方法:mapToInt、mapToDouble、mapToLong。
如,将Person中的age转换成数值流:

IntStream stream = list.stream().mapToInt(Person::getAge);

数值计算

每种数值流都提供了数值计算函数,如max、min、sum等。如,找出最大的年龄:

OptionalInt maxAge = list.stream().mapToInt(Person::getAge).max();

由于数值流可能为空,并且给空的数值流计算最大值是没有意义的,因此max函数返回OptionalInt,它是Optional的一个子类,能够判断流是否为空,并对流为空的情况作相应的处理。
此外,mapToInt、mapToDouble、mapToLong进行数值操作后的返回结果分别为:OptionalInt、OptionalDouble、OptionalLong

中间操作和收集操作总结

操作类型返回类型使用的类型/函数式接口函数描述符
filter中间Stream<T>Predicate<T>T -> boolean
distinct中间Stream<T>
skip中间Stream<T>long
map中间Stream<R>Function<T, R>T -> R
flatMap中间Stream<R>Function<T, Stream<R>>T -> Stream<R>
limit中间Stream<T>long
sorted中间Stream<T>Comparator<T>(T, T) -> int
anyMatch终端booleanPredicate<T>T -> boolean
noneMatch终端booleanPredicate<T>T -> boolean
allMatch终端booleanPredicate<T>T -> boolean
findAny终端Optional<T>
findFirst终端Optional<T>
forEach终端voidConsumer<T>T -> void
collect终端RCollector<T, A, R>
reduce终端Optional<T>BinaryOperator<T>(T, T) -> T
count终端long

Collector 收集

收集器用来将经过筛选、映射的流进行最后的整理,可以使得最后的结果以不同的形式展现。
collect 方法即为收集器,它接收 Collector 接口的实现作为具体收集器的收集方法。
Collector 接口提供了很多默认实现的方法,我们可以直接使用它们格式化流的结果;也可以自定义 Collector 接口的实现,从而定制自己的收集器。

归约

流由一个个元素组成,归约就是将一个个元素“折叠”成一个值,如求和、求最值、求平均值都是归约操作。

一般性归约

若你需要自定义一个归约操作,那么需要使用 Collectors.reducing 函数,该函数接收三个参数:

  • 第一个参数为归约的初始值
  • 第二个参数为归约操作进行的字段
  • 第三个参数为归约操作的过程

汇总

Collectors类专门为汇总提供了一个工厂方法:Collectors.summingInt
它可接受一 个把对象映射为求和所需int的函数,并返回一个收集器;该收集器在传递给普通的 collect 方法后即执行我们需要的汇总操作。

分组

数据分组是一种更自然的分割数据操作,分组就是将流中的元素按照指定类别进行划分,类似于SQL语句中的 GROUPBY

多级分组

多级分组可以支持在完成一次分组后,分别对每个小组再进行分组。
使用具有两个参数的 groupingBy 重载方法即可实现多级分组。

  • 第一个参数:一级分组的条件
  • 第二个参数:一个新的 groupingBy 函数,该函数包含二级分组的条件

Collectors 类的静态工厂方法

工厂方法返回类型用途示例
toListList<T>把流中所有项目收集到一个 ListList<Project> projects = projectStream.collect(toList());
toSetSet<T>把流中所有项目收集到一个 Set,删除重复项Set<Project> projects = projectStream.collect(toSet());
toCollectionCollection<T>把流中所有项目收集到给定的供应源创建的集合Collection<Project> projects = projectStream.collect(toCollection(), ArrayList::new);
countingLong计算流中元素的个数long howManyProjects = projectStream.collect(counting());
summingIntInteger对流中项目的一个整数属性求和int totalStars = projectStream.collect(summingInt(Project::getStars));
averagingIntDouble计算流中项目 Integer 属性的平均值double avgStars = projectStream.collect(averagingInt(Project::getStars));
summarizingIntIntSummaryStatistics收集关于流中项目 Integer 属性的统计值,例如最大、最小、 总和与平均值IntSummaryStatistics projectStatistics = projectStream.collect(summarizingInt(Project::getStars));
joiningString连接对流中每个项目调用 toString 方法所生成的字符串String shortProject = projectStream.map(Project::getName).collect(joining(", "));
maxByOptional<T>按照给定比较器选出的最大元素的 Optional, 或如果流为空则为 Optional.empty()Optional<Project> fattest = projectStream.collect(maxBy(comparingInt(Project::getStars)));
minByOptional<T>按照给定比较器选出的最小元素的 Optional, 或如果流为空则为 Optional.empty()Optional<Project> fattest = projectStream.collect(minBy(comparingInt(Project::getStars)));
reducing归约操作产生的类型从一个作为累加器的初始值开始,利用 BinaryOperator 与流中的元素逐个结合,从而将流归约为单个值int totalStars = projectStream.collect(reducing(0, Project::getStars, Integer::sum));
collectingAndThen转换函数返回的类型包含另一个收集器,对其结果应用转换函数int howManyProjects = projectStream.collect(collectingAndThen(toList(), List::size));
groupingByMap<K, List<T>>根据项目的一个属性的值对流中的项目作问组,并将属性值作 为结果 Map 的键Map<String,List<Project>> projectByLanguage = projectStream.collect(groupingBy(Project::getLanguage));
partitioningByMap<Boolean,List<T>>根据对流中每个项目应用断言的结果来对项目进行分区Map<Boolean,List<Project>> vegetarianDishes = projectStream.collect(partitioningBy(Project::isVegetarian));

转换类型

有一些收集器可以生成其他集合。比如前面已经见过的 toList,生成了 java.util.List 类的实例。
还有 toSettoCollection,分别生成 SetCollection 类的实例。
到目前为止, 我已经讲了很多流上的链式操作,但总有一些时候,需要最终生成一个集合——比如:

  • 已有代码是为集合编写的,因此需要将流转换成集合传入;
  • 在集合上进行一系列链式操作后,最终希望生成一个值;
  • 写单元测试时,需要对某个具体的集合做断言。

使用 toCollection,用定制的集合收集元素

stream.collect(toCollection(TreeSet::new));

还可以利用收集器让流生成一个值。 maxByminBy 允许用户按某种特定的顺序生成一个值。

数据分区

分区是分组的特殊情况:由一个断言(返回一个布尔值的函数)作为分类函数,它称分区函数。
分区函数返回一个布尔值,这意味着得到的分组 Map 的键类型是 Boolean,于是它最多可以分为两组: true是一组,false是一组。

分区的好处在于保留了分区函数返回true或false的两套流元素列表。

并行流

并行流就是一个把内容分成多个数据块,并用不不同的线程分别处理每个数据块的流。最后合并每个数据块的计算结果。

将一个顺序执行的流转变成一个并发的流只要调用 parallel() 方法

public static long parallelSum(long n){return Stream.iterate(1L, i -> i +1).limit(n).parallel().reduce(0L,Long::sum);
}

将一个并发流转成顺序的流只要调用 sequential() 方法

stream.parallel().filter(...).sequential().map(...).parallel().reduce();

这两个方法可以多次调用,只有最后一个调用决定这个流是顺序的还是并发的。

并发流使用的默认线程数等于你机器的处理器核心数。

通过这个方法可以修改这个值,这是全局属性。

System.setProperty("java.util.concurrent.ForkJoinPool.common.parallelism", "12");

并非使用多线程并行流处理数据的性能一定高于单线程顺序流的性能,因为性能受到多种因素的影响。
如何高效使用并发流的一些建议:

  1. 如果不确定, 就自己测试。
  2. 尽量使用基本类型的流 IntStream, LongStream, DoubleStream
  3. 有些操作使用并发流的性能会比顺序流的性能更差,比如limit,findFirst,依赖元素顺序的操作在并发流中是极其消耗性能的。findAny的性能就会好很多,应为不依赖顺序。
  4. 考虑流中计算的性能(Q)和操作的性能(N)的对比, Q表示单个处理所需的时间,N表示需要处理的数量,如果Q的值越大, 使用并发流的性能就会越高。
  5. 数据量不大时使用并发流,性能得不到提升。
  6. 考虑数据结构:并发流需要对数据进行分解,不同的数据结构被分解的性能时不一样的。

流的数据源和可分解性

可分解性
ArrayList非常好
LinkedList
IntStream.range非常好
Stream.iterate
HashSet
TreeSet

流的特性以及中间操作对流的修改都会对数据对分解性能造成影响。 比如固定大小的流在任务分解的时候就可以平均分配,但是如果有filter操作,那么流就不能预先知道在这个操作后还会剩余多少元素。

考虑终端操作的性能:如果终端操作在合并并发流的计算结果时的性能消耗太大,那么使用并发流提升的性能就会得不偿失。

http://www.hrbkazy.com/news/43994.html

相关文章:

  • 做h5网站设计百度推广登陆
  • wordpress 如何维护黑帽seo培训
  • 怎么做app网站ui原型徐州网站优化
  • 成考做那个网站的题比较好广告营销留电话网站
  • 个体户营业执照科研做企业网站吗推广搜索引擎
  • web网站开发的好书软件推广的渠道是哪里找的
  • 注册网站送金币东莞今天新增加的情况
  • 电子商务网站建设与维护实训题库网页制作基础教程
  • 星巴克网站开发票吗网址搜索引擎入口
  • 商务网站建设有哪几个步骤网站的优化seo
  • 网站安全评估怎么做天津网站优化软件
  • 开设赌场罪 网站开发四平网络推广
  • 专业旅游网站建设seo建站优化推广
  • 做网站需要多少钱 百度网络营销有什么特点
  • 深圳品牌网站设计公司seo工资服务
  • 邯郸做淘宝网站免费b站动漫推广网站2023
  • 天津武清做网站tjniuseo排名软件怎么做
  • 做网站需要什么基础爱战网关键词查询网站
  • html 购物网站长春网络推广优化
  • 承接设计网站建设sem推广优化
  • 杭州网站建设 网络服务友情链接出售平台
  • 建个网站在哪备案如何做网站seo
  • 用老域名做网站还是新域名网络广告有哪些形式
  • 环保网站模板全国疫情高中低风险区一览表
  • 月付商城网站建站seo优化运营专员
  • wordpress苹果客户端二十条优化
  • 如何登录网站空间推广网络营销外包公司
  • 网站技术招标怎么做网络整合营销方案ppt
  • 深圳福田高端网站建设百度一下就知道
  • 自己做首饰的好网站网站设计制作在哪能看