java 8 函数式编程实战

函数一二三等值的区分:

只要某个值满足以下三个条件,就能被称为一等值。

  1. 可以作为参数传递给函数
  2. 可以作为函数返回值
  3. 可以被赋值给变量

所以数字、字符串等常用的值都是一等的。如果仅满足第一条,而不能作为函数返回值或被赋值给变量,就称为二等的(Second-class)。假如三条都不满足,则称为三等的(Third-class)。

 

谓词:在数学上常用来表示一个类似函数的东西,接受一个参数,并返回true或false。

 

函数式接口:只定义一个抽象方法的接口。哪怕接口定义了很多默认方法,只要接口之定义了一个抽象方法,它就仍然是一个函数时接口

@FunctionalInterface 表示该接口会设计成一个函数式接口,但不是必须的,但对于为此设计的接口而言,使用它是比较好的做法。

如果lambda表达式抛出一个异常,那么抽象方法所生命的throws语句也必须与之匹配。

特殊的 void 兼容规则:

如果一个 Lambda 的主体是一个语句表达式, 它就和一个返回 void 的函数描述符兼容(当然需要参数列表也兼容)。例如,以下两行都是合法的,尽管List的add方法返回了一个boolean,而不是Consumer上下文(T -> void)所要求的void:

// Predicate返回了一个boolean
Predicate<String> p = s -> list.add(s);
// Consumer返回了一个void
Consumer<String> b = s -> list.add(s);

原始类型流特化:

为了避免暗含的装箱成本(int和Integer之间效率差异)

提供了IntStream,DoubleStream,LongStream的接口。

使用mapToInt()这类方法变成IntStream

使用boxed()方法变为对象流Stream<Integer>类型

同样的Optional也有OptionalInt OptionalLong OptionalDouble三种类型

 

可以使用静态方法Stream.of创建一个流

Stream.empty()得到一个空流
Files.lines()文件中使用返回一个流

 

 

 

 

 

 

集合api collection主要为了存储和访问数据,stream主要用于描述对数据的计算,集合讲的是数据,流讲的是计算。stream允许并提倡并行处理一个stream中的元素。

流的数据处理支持列斯数据库的操作以及函数式编程语言的常用操作。

流就是从支持数据处理操作的源生成的元素序列。

很多流操作本身返回一个流,这样可以多个操作连接起来形成一个大的流水线,这样就可以优化产生如:延迟和短路。

流水线操作可看作对数据源进行数据库式的查询。

 

从有序集合生成流时会保留原有的顺序,有列表生成流,其元素顺序与列表一致。

流是在概念上固定的数据结构(不能删除或者添加元素),只会按需生成,延迟创建的集合们只有在消费者需要才会计算值。

集合是急切创建的。如创建一个包含所有质数的流。

 

流只能遍历一次。再次使用就会抛异常说流已经被使用了。

流是内部迭代的,项目透明的并行处理,或用更优化的顺序进行处理。

若果使用集合collection外部迭代(用户去做迭代)都得自己优化是很困难的。

 

除非流水线上触发一个终端操作,否则中间操作不执行任何处理。因为中间操作都可以合并起来,在终端一次性全部处理。

 

终端操作 从流生成结果其结果是任何不是流的值。

流一般做的三件事:

一个数据源执行一个查询

一个中间操作链,形成一条流水线

一个终端操作,执行流水线,并形成结果。

 

 

 

 

流的limit(n)返回一个不超过给定长度的流与skip(n)返回一扔掉前n个元素的流(若元素不足n则返回一个空流)是互补的。

map()接受一个函数为参数,该函数被应用到每个元素上,并将其映射(创建一个新版本)成一个新元素。

faltmap():流的扁平化,让你把流中的每个值度换成另一个流,然后把所有的流连起来成为一个流。

anyMatch()流中是否有一个元素能匹配给定谓词。(短路或||)返回boolean终端操作

allMatch()流中元素是否都能匹配给定谓词(短路与&&)返回boolean终端操作

noneMatch()流中没有任何元素与给定谓词匹配。返回boolean终端操作

 

findAny()终端操作 返回当前流中的任意元素。

 

 

findFirst()返回流中出现的第一个元素

为何同时有findAny和findFirst,因为并行,找第一个元素在并行上限制更多,所以不关心返回元素是哪个则使用findAny因为并行时使用限制少。

 

T reduce(T identity, BinaryOperator<T> accumulator);

identity初始值

accumulator 将两个元素结合产生一个新值。如lambda (a,b) -> a+b;

如下:

numbers是一个集合

int sum = numbers.stream().reduce(0, (a,b) -> a*b);

 

也可以使用其重载版本不输入初始值。但会返回一个Optional对象:

Optional<T> reduce(BinaryOperator<T> accumulator);

当然也可以计算最大值最小值

List<Integer> numbers = Arrays.asList(3,4,5,1,2);
int sum = numbers.stream().reduce(0, (a, b) -> a + b);
System.out.println(sum);

int sum2 = numbers.stream().reduce(0, Integer::sum);
System.out.println(sum2);

int max = numbers.stream().reduce(0, (a, b) -> Integer.max(a, b));
System.out.println(max);

Optional<Integer> min = numbers.stream().reduce(Integer::min);
Integer::min等价于 lambda(x,y)-> x<y?x:y不过前者更可读
min.ifPresent(System.out::println);

int calories = menu.stream()
                   .map(Dish::getCalories)
                   .reduce(0, Integer::sum);
System.out.println("Number of calories:" + calories);

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值