Java8之Stream

本文详细探讨了Java8的新特性,包括Stream API的使用,Lambda表达式的概念与应用,以及函数式接口的重要性和实践。通过实例解析了行为参数化、流处理、函数式编程的基本思想,同时介绍了如何利用Java8的默认方法和方法引用简化代码。此外,还讨论了Collector在流操作中的作用以及如何自定义函数式接口。
摘要由CSDN通过智能技术生成

为什么关心Java8

Java8与并发编程

答:

Java8之前,必须利用多线程才能使用多个内核,问题是线程用起来很难,也容易出错,
Java8提供了一个新的API,Stream支持多处理器的并行操作
在多个处理器内核之间使用synchronize,其代价往往比预期要大得多

行为参数化是什么

答:
:

例如:匿名内部类,但是还不够简洁,请看Java8,函数式编程,lambda表达式

“流处理”你能想到什么

答:
:

Java的流处理,一个程序的输入可能是另一个程序的输出(System.in和System.out)

linux的流处理:cat file1 file2 | sort | tail -3  

函数式编程的基石,两点

答:


1.没有共享的可变数据
2.将方法和函数传递给其他方法的能力

方法作为参数传递进去举一个例子

答:

筛选红苹果和绿苹果。P12

Function<Apple,Boolean>与Predicate的区别

答:

函数与谓词

思考

题:

filterApples(apples,Apple::isGreen)
上面这个可以筛选出绿苹果

问题是:isGreen这种只能用一两次的短方法写一堆定义有点烦,还有其他解决方式吗?
答:


filterApples(apples,(Apple a) -> "green".equals(a.getColor()));

默认方法的好处

答:



Java8之前,接口若要扩充一个方法,那么其子类都要实现这个方法,现在不需要了,提供一个default方法即可

方法匿名与有方法名比,好处是什么

答:



普通方法的坏处,写的少,想得多

什么是函数式接口

答:



只定义一个抽象方法的接口

思考

问题:
B是函数式接口吗?

interface A {
	void f();
}
interface B extends A{
	void f();
}

答:



:不是,有两个add方法

看下面的函数描述符代表什么意思

() -> void
(Apple) -> int

对于下面的函数描述符,你会使用哪种函数式接口

  1. T -> R
  2. (int,int) -> int
  3. T -> void
  4. () -> T
  5. (T,U) -> R
  6. (T,T) -> T
    答:


7. Function<T,R>
8. IntBinaryOperator 
9. Consumer<T>
10.Supplier<T>
BiFunction<T,U,R>
BinaryOperator<T> 

Predicate与IntPredicate的区别

答:



IntPredicate不需要自动装箱与拆箱,节省性能

lambda表达式找对应函数式接口

1.布尔表达式(List list) -> list.isEmpty()
2.创建对象 () -> new Apple()
3.消费一个对象 (Apple a) -> sout(a.getWeight())
4.从一个对象中选择或者提取 (String s) -> s.length()
5.合并两个值 (int a,int b) -> a*b
6.比较两个对象 (Apple a1,Apple a2) -> a1.getWeight . CompareTo(a2.getWeight)

答:




Predicate<List<String>>
Supplier<Apple>
Consumer<Apple>
Function<String,Integer>或ToIntFunction<String>
IntBinaryOperator
Comparator<Apple>或BiFunction<Apple,Apple,Integer>

什么是void兼容

答:


Predicate<Apple> p = (Apple a) -> list.add(a)
和
Consumer<Apple> c = (Apple a) -> list.add(a)
语法都不会报错,因为Consumer的返回是void

Objective o = () -> {sout(xxx)}为什么不能通过编译

答:


:目标类型object不是一个函数式接口

为什么lambda表达式使用局部变量必须final修饰,而实例变量不需要

答:




实例变量都存储在堆中,局部变量保存在栈上。如果lambda可以直接访问局部变量,且lambda是在一个线程中使用,可能会在分配该变量的线程将这个变量回收之后,去访问该变量。因此Java在访问自由局部变量时,实际上是在访问它的副本,而不是在访问原始变量,如果局部变量是final仅赋值一次那就没什么了

如何理解闭包、匿名类、lambda表达式

答:




1.闭包是一个函数的实例,可以无限制地访问那个函数的非本地变量。
2.闭包可以作为参数传递给另外一个函数,它也可以访问和修改其作用域之外的变量,类似于Java的lambda和匿名类
3.但有一个限制,不能修改局部变量的内容,变量必须隐式最终,可以认为lambda是对值封闭,而不是对变量封闭。
4.这种限制存在的原因在于局部变量保存在栈上,并且隐式表示他们限于其所在线程
Java8实战P52

思考

省略了哪些?

inventory.sort(comparing(Apple::getWeight))

1.Comparator.comparing(Function<Apple,Integer>)

lambda方法引用的基本思想

如果一个lambda代表的只是直接调用这个方法,那最好还是用名称来调用它,而不是描述如何调用它

写出下面的lambda表达式的方法引用

(Apple a) -> a.getWeight()
() -> Thread.currentThread().dumpStack()
(str, i) -> str.substring(i)
(String s) -> sout(s)

答:

Apple::getWeight
Thread.currentThread::dumpStack
String::substring
System.out::println

三类方法引用

(args) -> ClassName.staticMethod(args)
(agr0,rest) -> arg0.instanceMethod(rest)
(args) -> expr.instanceMethod(args)

答:

ClassName::staticMethod
ClassName::instanceMethod
expr::instanceMethod

list.sort((s1,s2) -> s1.compareToIgnoreCase(s2))可以简化成方法引用吗

String::compareToIgnoreCase,相当于第二类

思考

Supplier<Apple> c1 = Apple::new
对应无参Apple()Apple(Integer weight) 的Apple::new还能对应Supplier吗?

答:


不能,应该对应Function<Integer,Apple>

比较器复合、谓词复合、函数复合

Java8实战P60

流与集合的区别

1.当用户想看一部电影时,可以买DVD看,也可以在线观看,DVD是将整个电影下载下来了,而在线只是下载用户看到的和缓存的一小部分
2.流的数据处理类似于数据库,如filter、map、reduce,而集合没有
3.流是内部迭代,集合是外部迭代

将[“hello”,“world”],去重返回[H,e,l,W,o,r,d]

错误示范:

stream.map(word -> word.split(""))
	.distinct()
	.collect(toList())

正确做法:
思路:
Stream words
Stream words.flatMap(???).distinct()
???里应该是hello切割成数组String[],再转Stream,类推world
flatMap再将两个stream合为一个Stream

stream.flatMap(word -> Arrays.stream(word.split("")))
                .distinct().collect(Collectors.toList());

stream.map(w -> w.split(""))
                .flatMap(Arrays::stream)
                .distinct()
                .collect(Collectors.toList());
上面两个居然都行,思路一样的

给定[1,2,3]和[3,4],返回[{1,3},{1,4},{2,3},{2,4},{3,3},{3,4}]

int[] num1
int[] num2

num1.stream().flatMap(i -> {
	num2.stream().map(
		j -> new int[]{i,j}
	)
})...

检查是否至少匹配一个元素

boolean = stream.anyMatch(apple -> {
	"red".equals(apple.getColor())
})

检查是否匹配所有元素

allMatch

函数式接口

函数式接口好处(TODO)

自定义函数式接口

jdk中的函数式接口

lambda表达式

lambda表达式好处(TODO)

匿名内部类转lambda表达式

Lambda 语法简化

StreamAPI

streamAPI好处(TODO)

Stream的生成方式

stream的操作类型Intermediate

stream的操作类型Terminal

Collector

collector干嘛用的

collector中的5个抽象方法

supplier
accumulator
combiner
finisher
characteristics

Collectors

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值