一、条件:
必须有接口,有且仅有一个抽象方法:函数式接口
@FunctionalInterface:标记是否为函数式接口
二、接口类型
1.comsumer接口(消费接口)对应的方法是accept
void accept( T);有参无返回值
Consumer<String> consumer = s-> System.out.println(s);
consumer.accept("传入消费的数据");
eg:forEach(s-> System.out.println(s))
2.Supplier接口(生产接口)对应的方法是get
T get();无参有返回值
3.Function接口
有参与返回值
Arrays.stream(new int[]{1,3,4,5}).map(s->s+1).forEach(s-> System.out.println(s));
其中map就用到了function接口,map为映射
三、stream流的操作
1.基本操作
public class Stream01 {
public static void main(String[] args) {
//对下面数组求和 外部迭代
int []arr = new int[]{1,2,3};
int sum = 0;
for (int i : arr) {
sum+=i;
}
System.out.println("普通方法求得数组的和为:"+sum);
//stream流操作 内部迭代
int sum1 = IntStream.of(arr).sum();
System.out.println("stream流表达式求得数组的和为:"+sum1);
}
}
2.中间操作,终止操作,惰性求值
public class Lambda {
public static void main (String[]args){
//对下面数组求和
int[] arr = new int[]{1, 2, 3};
//stream流操作
int sum = IntStream.of(arr).map(i -> i * 2).sum();
System.out.println("stream流表达式求得数组的和为:" + sum);
//惰性求值,没有对流执行终止操作,所以sum方法没有执行,这就叫惰性求值
IntStream intStream = IntStream.of(arr).map(Lambda::sum);
System.out.println("因为惰性求值,没有执行....");
System.out.println("-----------------------------------------");
System.out.println("当执行了终止操作后就会执行,惰性求值的方法才会执行");
intStream.sum();
}
public static int sum ( int i){
System.out.println("对传入的i值加5处理");
return i + 5;
}
}
结果:
stream流表达式求得数组的和为:12
因为惰性求值,没有执行....
-----------------------------------------
当执行了终止操作后就会执行,惰性求值的方法才会执行
对传入的i值加5处理
对传入的i值加5处理
对传入的i值加5处理
2.1、filter:需要传入一个Preedicate函数式接口的匿名对象
String name = "我aa 爱aaa 中aaaa 国aaaaa";
Stream.of(name.split(" ")).map(s->s.length()).filter(i->i>4).forEach(System.out::println);
2.2、flatMap:需要传入一个Function函数式接口的匿名对象
实用于:A元素下面有一个集合B元素,去获得所有A元素中B元素集合的流
public class Stream04 {
public static void main(String[] args) {
List<Student> stuList = new ArrayList<>();
stuList.add(new Student(1));
stuList.add(new Student(2));
//遍历获得student元素 并获得student元素中的list集合 并转换为流形式
stuList.stream().flatMap(student->student.list.stream()).forEach(System.out::print);
}
}
class Student{
List<Integer> list ;
public Student(int k){
list = new ArrayList<>();
list.add(1*k);
list.add(2*k);
list.add(3*k);
}
}
结果:
123246
Process finished with exit code 0
2.3、peek:需要传入一个Consumer函数式接口的匿名对象
public static void main(String[] args) {
String name = "我aa 爱aaa 中aaaa 国aaaaa";
Stream.of(name.split(" ")).peek(System.out::print).forEach(System.out::println);
}
结果:
我aa我aa
爱aaa爱aaa
中aaaa中aaaa
国aaaaa国aaaaa
2.4、limit:限制
public class Stream06 {
public static void main(String[] args) {
//随机无限流 产生整数 然后过滤器只取大于100的 用limit限制取10个
new Random().ints().filter(i->i>100).limit(10).forEach(System.out::println);
}
}
2.5、去重排序
public static void main(String[] args) {
// 对数组流,先过滤重复,在排序
Arrays.asList(3, 1, 2, 1).stream().distinct().sorted().forEach(System.out::println);
}
3、其他:
3.1、orEachOrder:保证在并行流操作时不混乱
public static void main(String[] args) {
// 用了parallelStream 相当于起了线程池 不同线程输出会混乱
Arrays.asList(3, 1, 2, 1).parallelStream().forEach(i-> System.out.println(Thread.currentThread()+":"+i));
System.out.println("--------------------------------------------");
//用forEachOrdered可以保证顺序不乱
Arrays.asList(3, 1, 2, 1).parallelStream().forEachOrdered(i-> System.out.println(Thread.currentThread()+":"+i));
}
3.2、collect
把流收集为其他类型,比如list、set等
public static void main(String[] args) {
//将数组元素收集为list集合 不能用new int 因为流没有子类基本数据类型,需要装箱操作
List<Integer> list = Arrays.stream(new Integer[]{1, 2,3}).collect(Collectors.toList());
System.out.println(list);
}
3.3、reduce
public static void main(String[] args) {
//用*号拼接
Optional<String> reduce = Stream.of("a-b-c-d".split("-")).reduce((str1, str2) -> str1 + "*" + str2);
System.out.println(reduce.get());
//可以给一个初始值"" 然后再初始值基础上再+
String reduce1 = Stream.of("a-b-c-d".split("-")).reduce("", (str1, str2) -> str1 + "*" + str2);
System.out.println(reduce1);
//比如要计算劈开后的总长度 先获取长度的流 再在0的基础上相加
Integer reduce2 = Stream.of("a-b-c-d".split("-")).map(str -> str.length()).reduce(0, (i, j) -> i + j);
System.out.println(reduce2);
}
3.4、min、max、count
//max需要自定义比较策略 这里时按长度的策略比较 min类似
Optional<String> max = Stream.of("aa-bbb-ccc-dddd".split("-")).max((str, str2) -> str.length() - str2.length());
System.out.println(max.get());
//count返回流的长度
long count = Stream.of("aa-bbb-ccc-dddd-ee".split("-")).count();
System.out.println(count);
上面介绍的都是非短路操作,意思遇到这些方法也会把所有的流遍历完。
3.5、短路操作:遇到下面的方法就不会在继续遍历流了
//findFirst:找到第一个就中断无限流
OptionalInt first = new Random().ints().findFirst();
System.out.println(first.getAsInt());
anyMatch表示,判断的条件里,任意一个元素成功,就短路(不在继续遍历流),返回true
allMatch表示,判断条件里的元素,所有的都是,返回true,遇到一个false就短路
noneMatch跟allMatch相反,判断条件里的元素,所有的都不是,返回true,有一个匹配上就短路返回false
5>并行流:多线程
1>普通流情况下 一个一个打印,下面使用并行流(多线程):
2>并行流,串行流同时使用,以后面的为准:
public class Stream12 {
public static void main(String[] args) {
//串行parallel 并行sequential同时使用 以后面为准 所以下面是串行
IntStream.range(1,100).parallel().sequential().peek(Stream12::print).count();
}
public static void print(int i){
System.out.println(i);
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}