学习目标
java
- 能够掌握Lambda表达式的标准格式与省略格式(重点)
()->{}
(参数)->{重写接口中的抽象方法的方法体}
(int a,int b)->{}==>省略数据类型 (a,b)->{}
(int a)->{}==>省略数据类型 a->{}
a->{只有一行代码}==>a->代码(return ; {} 一起省略)
- 能够通过集合、映射或数组方式获取流(重点)
Collection集合中方法default Stream<E> stream()直接把集合转换为Stream流
ArrayList<Integer> list = new ArrayList<>();
Stream<Integer> stream1 = list.stream();
Stream接口中的静态方法static <T> Stream<T> of(T... values) 把数组转换为Stream流
Stream<Integer> stream1 = Stream.of(1, 2, 3, 4, 5, 6, 7, 8);
String[] arr1 = {"a", "b", "c"};
Stream<String> stream3 = Stream.of(arr1);
- 能够掌握常用的流操作(重点)
forEach:遍历
count:统计个数
fiter:过滤
limit:获取前n个
skip:跳过前n个
map:映射,把一种数据类型转换为另外一种数据类型
concat:组合 把两个流组合为一个流
- 能够将流中的内容收集到集合和数组中(重点)
List<String> list = stream.collect(Collectors.toList());
Set<String> set = stream.collect(Collectors.toSet());
Object[] arr = stream.toArray();
第一章 Lambda表达式(重点)
1.函数式编程思想概述
面向对象思想:
做一件事情,找一个能够解决这个事情的对象,调用对象的方法来完成这件事情
函数式编程思想:
重视的是结果,怎么做事情,不重视完成的过程,找谁来做
2.使用Lambda表达式简化匿名内部类(重点)
java
package com.itheima.demo01Lambda;
public class Demo01Lambda {
public static void main(String[] args) {
//使用匿名内部类创建一个新的线程
new Thread(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"-->使用匿名内部类的方式,实现多线程程序!");
}
}).start();
//使用Lambda表达式简化匿名内部类创建一个新的线程
new Thread(()->{
System.out.println(Thread.currentThread().getName()+"-->使用Lambda表达式的方式,实现多线程程序!");
}).start();
}
}
3.Lambda表达式的语法(重点)
Lambda表达式的语法:
由一些参数,一个箭头,一些代码组成
格式:
(参数列表)->{重写抽象方法的方法体}
Lambda表达式作用:简化匿名内部类
lambda表达式使用前提:必须有接口,接口中有且只能有一个抽象方法(函数式接口)
Lambda表达式是可推导,可省略:能推导出来,Lambda表达式重写的就是接口中唯一的抽象方法
- (参数列表):重写抽象方法的参数
- ->:传递(固定写法):可以把参数传递到方法体中使用
- {}:重写抽象方法的方法体
java
/*
Lambda表达式的基本格式
( )->{ } Runnable接口-->public abstract void run();
一些参数,一个箭头,一些代码
():重写接口中唯一抽象方法的参数列表,没有参数就空着,有多个参数使用逗号隔开
->:传递,可以把参数传递给{ }方法体使用
{ }:重写接口中唯一抽象方法的方法体
Lambda表达式的使用前提:
1.必须有接口
2.接口中只能有且仅有一个抽象方法(函数式接口)
注意:
Lambda表达式是可推导可省略
Lambda表达式的目的就是重写接口中唯一的抽象方法
接口的方法只有一个,可以推导出重写的就是接口中唯一的抽象方法,所以可以简化代码
*/
4.使用Lambda表达式重写有参数有返回值的方法(重点)
java
package com.itheima.demo01Lambda;
import java.util.Arrays;
import java.util.Comparator;
/*
使用Lambda表达式重写有参数有返回值的方法(重点)
需求:
创建一个数组,数组的类型使用Person
创建3个Person对象,存储到数组中
使用Arrays数组工具类中的方法sort,根据比较器产生的规则对Person对象进行排序(年龄升序)
*/
public class Demo02Lambda {
public static void main(String[] args) {
//创建一个数组,数组的类型使用Person
Person[] arr = new Person[3];
//创建3个Person对象,存储到数组中
arr[0] = new Person("张三",18);
arr[1] = new Person("李四",20);
arr[2] = new Person("王五",19);
System.out.println("排序前数组中的元素:"+Arrays.toString(arr));
//使用Arrays数组工具类中的方法sort,根据比较器产生的规则对Person对象进行排序(年龄升序)
Arrays.sort(arr, new Comparator<Person>() {
@Override
public int compare(Person o1, Person o2) {
//o1-o2:升序 o2-o1:降序
return o1.getAge()-o2.getAge();
}
});
System.out.println("排序后数组中的元素:"+Arrays.toString(arr));
//使用Lambda表达式简化匿名内部类 public int compare(Person o1, Person o2)
Arrays.sort(arr,(Person o1, Person o2)->{
return o2.getAge()-o1.getAge();
});
System.out.println("排序后数组中的元素:"+Arrays.toString(arr));
}
}
java
package com.itheima.demo01Lambda;
public class Person {
private String name;
private int age;
public Person() {
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
5.Lambda表达式简化格式
java
package com.itheima.demo01Lambda;
import java.util.Arrays;
import java.util.Comparator;
/*
Lambda表达式简化格式:可以使用,也可以不使用
Lambda表达式使用前提:有接口,接口中有且仅有一个抽象方法(函数式接口)
Lambda表达式是可推导,可以省略的
可以推导出,Lambda表达式重写的就是接口中唯一的抽象方法
也可以推导出方法的参数和方法有没有返回值,可以可以对参数和返回值在进行简化
格式:
(参数列表)->{重写抽象方法的方法体}
简化:
1.(参数列表):参数列表的数据类型是可以推导出来的,可以省略
(int a)-->(a)
(int a,String s)-->(a,s)
2.(参数列表):参数列表中只有一个参数,()小括号也可以省略,但是参数列表没有参数,()小括号不能省略
(int a)-->a
()-->不能省略-->()
3.{重写抽象方法的方法体}:重写的方法体,如果只有一行代码(java中行是以分号隔开的)
无论方法是否有返回值
{ }和一行代码结束的分号(;)和return关键字可以省略不写
但是他们必须一起省略
*/
public class Demo03Lambda {
public static void main(String[] args) {
//使用匿名内部类创建新的线程
new Thread(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"-->使用匿名内部类的方式,实现多线程程序!");
}
}).start();
//使用Lambda表达式简化匿名内部类
new Thread(()->{
System.out.println(Thread.currentThread().getName()+"-->使Lambda表达式的方式,实现多线程程序!");
}).start();
//简化Lambda表达式
new Thread(()->System.out.println(Thread.currentThread().getName()+"-->使Lambda表达式的方式,实现多线程程序!")).start();
System.out.println("----------------------------------------");
//创建一个数组,数组的类型使用Person
Person[] arr = new Person[3];
//创建3个Person对象,存储到数组中
arr[0] = new Person("张三",18);
arr[1] = new Person("李四",20);
arr[2] = new Person("王五",19);
System.out.println("排序前数组中的元素:"+ Arrays.toString(arr));
//使用Arrays数组工具类中的方法sort,根据比较器产生的规则对Person对象进行排序(年龄升序)
Arrays.sort(arr, new Comparator<Person>() {
@Override
public int compare(Person o1, Person o2) {
//o1-o2:升序 o2-o1:降序
return o1.getAge()-o2.getAge();
}
});
System.out.println("排序后数组中的元素:"+Arrays.toString(arr));
//使用Lambda表达式简化匿名内部类 public int compare(Person o1, Person o2)
Arrays.sort(arr,(Person o1, Person o2)->{
return o2.getAge()-o1.getAge();
});
System.out.println("排序后数组中的元素:"+Arrays.toString(arr));
//简化Lambda表达式
Arrays.sort(arr,(o1,o2)->o1.getAge()-o2.getAge());
System.out.println("排序后数组中的元素:"+Arrays.toString(arr));
}
}
第二章 函数式接口(了解)
1.函数式接口的定义
java
package com.itheima.demo02FunctionalInterface;
/*
函数式接口:接口中有且仅有一个抽象方法的接口
注意:
1.接口中没有抽象方法不行
2.接口中除了唯一的抽象方法,还可以包含其他的方法(默认,静态,私有)
注解:
@FunctionalInterface:检测接口是否为一个函数式接口
*/
@FunctionalInterface
public interface MyFunction {
//定义抽象方法
public abstract void show(int a);
public static void show02(){
System.out.println("静态方法");
}
public default void show03(){
System.out.println("默认方法");
}
}
2.函数式接口的作用
java
package com.itheima.demo02FunctionalInterface;
/*
函数式接口的作用:
可以使用函数式接口作为方法的参数类型和返回值类型使用
参数和返回值就可以使用Lambda表达式简化代码了
Lambda表达式可以看成就是接口的实现类对象的一种
*/
public class Demo01MyFunction {
public static void main(String[] args) {
//调用method方法,方法的参数MyFunction是一个接口,需要传递接口的实现类对象,给接口变量赋值
method(new MyFunction() {
@Override
public void show(int a) {
System.out.println("匿名内部类的方式,重写show方法-->"+a);
}
},10);
//调用method方法,方法的参数MyFunction是一个函数式接口,需要传递接口的实现类对象,给接口变量赋值
//使用Lambda表达式作为接口的实现类对象
method((int a)->{
System.out.println("Lambda表达式的凡是,重写show方法-->"+a);
},10);
//简化Lambda表达式
method(a-> System.out.println("Lambda表达式的凡是,重写show方法-->"+a),10);
System.out.println("-------------");
//多态 接口 实现类对象
//MyFunction my = a-> System.out.println(a);
MyFunction my = getMyFunction();
my.show(100);
}
/*
定义一个方法,方法的参数类型使用函数式接口MyFunction
MyFunction my = new MyFunction() {
@Override
public void show(int a) {
System.out.println("匿名内部类的方式,重写show方法-->"+a);
}
};
my.show(10);
--------------------------------
MyFunction my = (int a)->{
System.out.println("Lambda表达式的凡是,重写show方法-->"+a);
}
my.show(10);
*/
public static void method(MyFunction my,int i){
my.show(i);
}
/*
定义一个方法,方法的返回值类型使用函数式接口
*/
public static MyFunction getMyFunction(){
//方法的返回值类型是MyFunction接口,方法就需要返回一个MyFunction接口的实现类对象
/*return new MyFunction() {
@Override
public void show(int a) {
System.out.println(a);
}
};*/
//方法的返回值类型是MyFunction函数式接口,所以就可以返回一个Lambda表达式作为接口的实现类对象
/*return (int a)->{
System.out.println(a);
};*/
//简化Lambda表达式
return a-> System.out.println(a);
}
}
3.函数式接口:Consumer
java
package com.itheima.demo02FunctionalInterface;
import java.util.function.Consumer;
/*
java.util.function.Consumer<T>:函数式接口
接口中唯一的抽象方法:
void accept(T t) :消费一个指定泛型类型的数据
Consumer接口的泛型使用什么类型,就可以使用accept方法消费(使用)一个什么类型的数据
至于我们怎么使用这个数据,看心情(想怎么用就怎么用,可以计算,可以输出...)
*/
public class Demo02Consumer {
public static void main(String[] args) {
//调用method方法,方法的参数Consumer是一个接口,可以传递接口的匿名内部类对象,给接口变量赋值
method(new Consumer<String>() {
@Override
public void accept(String s) {
//怎么使用使用这个参数,就怎么使用(看心情)
System.out.println(s);
}
},"abc");
//调用method方法,方法的参数Consumer是一个函数式接口,可以传递Lambda表达式作为接口的实现类对象,给接口变量赋值
method((String s)->{
System.out.println(s);
},"abc");
//简化Lambda表达式
method(s-> System.out.println(s),"abc");
}
/*
定义一个方法,方法的参数
传递Consumer接口,泛型使用String
传递一个字符串参数
在方法内部使用Consumer接口中的方法accept,对字符串参数进行消费
*/
public static void method(Consumer<String> con,String s){
con.accept(s);
}
}
4.函数式接口:Predicate
java
package com.itheima.demo02FunctionalInterface;
import java.util.function.Predicate;
/*
java.util.function.Predicate<T>:函数式接口
接口中唯一的抽象方法:
boolean test(T t) 用于对接口指定泛型类型的数据进行判断
Predicate接口的泛型使用什么类型,就可以使用test方法判断数据是否满足要求
满足要求:test方法返回true
不满足要求;test方法返回false
*/
public class Demo03Predicate {
public static void main(String[] args) {
//调用method方法,方法的参数Predicate是一个接口,可以传递接口的匿名内部类对象,为接口变量赋值
method(new Predicate<String>() {
@Override
public boolean test(String s) {
//判断字符串的长度是否大于5
return s.length()>5;
}
},"aaa11111");
//调用method方法,方法的参数Predicate是一个函数式接口,可以传递Lambda表达式作为接口的实现类对象,为接口变量赋值
method((String s)->{
return s.length()>5;
},"aaa");
//简化Lambda表达式
method(s->s.length()>5,"afdfasfad");
}
/*
定义一个方法,方法的参数
传递Predicate接口,泛型使用String
传递一个String类型的字符串
在方法内部使用Predicate接口中的方法test对字符串参数进行判断
*/
public static void method(Predicate<String> pre,String s){
boolean b = pre.test(s);
System.out.println(b);
}
}
5.函数式接口:Function
java
package com.itheima.demo02FunctionalInterface;
import java.util.function.Function;
/*
java.util.function.Function<T,R>:函数式接口
接口中唯一的抽象方法:
R apply(T t) 根据参数类型T获取类型R的接口,用于类型转换 T-->R
例如:
Function<String,Integer>:根据传递String类型的数据,获取Integer类型的结果 "123" Integer.parseInt("123")
Function<String,Person>:根据传递String类型的数据,获取Person类型的结果 "aaa" new Person("aaa")
...
*/
public class Demo04Function {
public static void main(String[] args) {
//调用method方法,方法的参数Function是一个接口,可以传递接口的匿名内部类对象,为接口变量赋值
method(new Function<String, Integer>() {
@Override
public Integer apply(String s) {
//把字符串的整数,解析为一个整数返回
return Integer.parseInt(s);
}
},"100");
//调用method方法,方法的参数Function是一个函数式接口,可以传递Lambda表达式作为接口的实现类对象,为接口变量赋值
method((String s)->{
return Integer.parseInt(s);
},"200");
//简化Lambda表达式
method(s->Integer.parseInt(s),"300");
}
/*
定义一个方法,方法的参数
使用Function接口,接口的泛型使用<String,Integer>
传递一个String类型的参数
在方法内部使用Function接口中的方法apply,把String类型的数据转换为Integer返回
*/
public static void method(Function<String,Integer> fun,String s){
Integer in = fun.apply(s);
System.out.println(in+10);
}
}
6.函数式接口:Supplier
java
package com.itheima.demo02FunctionalInterface;
import java.util.Random;
import java.util.function.Supplier;
/*
java.util.function.Supplier<T>:函数式接口
接口中唯一的抽象方法:
T get() 用来获取一个接口指定泛型类型的数据
Supplier接口使用什么泛型,就可以使用get方法获取一个什么类型的数据
*/
public class Demo05Supplier {
public static void main(String[] args) {
//调用method方法,方法的参数Supplier是一个接口,可以传递接口的匿名内部类对象,为接口变量赋值
method(new Supplier<Integer>() {
@Override
public Integer get() {
return 10;
}
});
//调用method方法,方法的参数Supplier是一个函数式接口,可以传递Lambda表达式作为接口的实现类对象,为接口变量赋值
method(()->{
return 10;
});
//简化Lambda表达式
method(()->10);
method(()->new Random().nextInt(100));
}
/*
定义一个方法,方法的参数
使用Supplier接口,接口的泛型使用Integer
在方法内部使用Supplier接口中的方法get,获取一个Integer类型的数据返回
*/
public static void method(Supplier<Integer> sup){
Integer in = sup.get();
System.out.println(in);
}
}
7.函数式接口的总结
函数式接口一般都作为方法的参数(返回值类型)
方法的参数是一个函数式接口,那么我们就可以传递lambda表达式作为接口的一种实现类对象
为方法的参数接口变量进行赋值
第三章 Stream
1.Sream流概述
我们可以把集合|数组,转换为Stream流,使用Stream流中的方法,对集合|数组进行操作
2.Stream流的基本体验
java
package com.itheima.demo03Stream;
import java.util.ArrayList;
import java.util.List;
/*
不使用Stream流,使用传统的方式遍历集合
*/
public class Demo01ArrayList {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("张无忌");
list.add("周芷若");
list.add("赵敏");
list.add("张强");
list.add("张三丰");
//1.首先筛选出所有姓张的人,把姓张的人存储到一个新的集合中
List<String> zhangList = new ArrayList<>();
for (String s : list) {
if(s.startsWith("张")){
zhangList.add(s);
}
}
System.out.println(zhangList);//[张无忌, 张强, 张三丰]
//2.然后筛选名字中有三个字的人,把名字有三个字的人存储到一个新的集合中
List<String> threeList = new ArrayList<>();
for (String s : zhangList) {
if(s.length()==3){
threeList.add(s);
}
}
System.out.println(threeList);//[张无忌, 张三丰]
//3.对最后得到的结果threeList进行遍历数组
for (String s : threeList) {
System.out.println(s);
}
}
}
java
package com.itheima.demo03Stream;
import java.util.ArrayList;
import java.util.List;
/*
使用Stream流的方式操作集合:Stream流可以使用代码变的更加优雅
把集合|数组转换为Stream流
使用Stream流中的方法,操作数组和集合
目的:
简化代码
*/
public class Demo02Stream {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("张无忌");
list.add("周芷若");
list.add("赵敏");
list.add("张强");
list.add("张三丰");
//1.首先筛选出所有姓张的人,把姓张的人存储到一个新的集合中
//2.然后筛选名字中有三个字的人,把名字有三个字的人存储到一个新的集合中
//3.对最后得到的结果threeList进行遍历数组
//把集合转换为Stream流
list.stream()
.filter(s->s.startsWith("张"))
.filter(s->s.length()==3)
.forEach(s-> System.out.println(s));
}
}
3.流式思想概述

4.获取Stream流的方式(重点)
java
package com.itheima.demo03Stream;
import java.util.*;
import java.util.stream.Stream;
/*
获取Stream流的方式(重点)
1.使用Collection接口中,定义了一个方法stream,可以把集合转换为Stream流
(JDK1.8之后)default Stream<E> stream() 此方法只能Collection接口下的单列集合可以使用
2.使用Stream接口中的方法of,可以把可变参数(数组)转换为Stream流
java.util.stream.Stream<T>接口
(JDK1.8之后)static <T> Stream<T> of(T... values) 方法的参数是一个可变参数,也可以传递数组
*/
public class Demo03Stream {
public static void main(String[] args) {
show02();
}
/*
把数组转换为Stream流
注意:
看到方法的参数是一个可变参数,就可以传递数组,因为可变参数底层就是一个数组
(JDK1.8之后)static <T> Stream<T> of(T... values) 方法的参数是一个可变参数,也可以传递数组
*/
private static void show02() {
Stream<Integer> stream1 = Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9);
Stream<String> stream2 = Stream.of("a", "b", "c");
String[] arr1 = {"a", "b", "c"};
Stream<String> stream3 = Stream.of(arr1);
//注意:数组的数据类型必须是包装类
int[] arr2 = {1,2,3};
Stream<int[]> stream4 = Stream.of(arr2);
Integer[] arr3 = {1,2,3};
Stream<Integer> stream5 = Stream.of(arr3);
}
/*
把集合转换为Stream流
*/
private static void show01() {
ArrayList<Integer> list = new ArrayList<>();
Stream<Integer> stream1 = list.stream();
LinkedList<String> linked = new LinkedList<>();
Stream<String> stream2 = linked.stream();
HashSet<Integer> set = new HashSet<>();
Stream<Integer> stream3 = set.stream();
HashMap<String,String> map = new HashMap<>();
//map.stream();//Cannot resolve method 'stream()' Map集合不能直接转换为Stream
//获取Map集合中所有key
Set<String> keySet = map.keySet();
Stream<String> stream4 = keySet.stream();
//获取Map集合中所有的value
Collection<String> values = map.values();
Stream<String> stream5 = values.stream();
//获取Map集合中所有的Entry对象
Set<Map.Entry<String, String>> entrySet = map.entrySet();
Stream<Map.Entry<String, String>> stream6 = entrySet.stream();
}
}
5.Stream的常用方法(重点)
流模型的操作很丰富,这里介绍一些常用的API。这些方法可以被分成两种:
- 终结方法 :返回值类型不再是
Stream
接口自身类型的方法,因此不再支持类似StringBuilder
那样的链式调用。本小节中,终结方法包括count
和forEach
方法。 - 非终结方法 :返回值类型仍然是
Stream
接口自身类型的方法,因此支持链式调用。(除了终结方法外,其余方法均为非终结方法。)
函数拼接与终结方法
在上述介绍的各种方法中,凡是返回值仍然为Stream
接口的为函数拼接方法 ,它们支持链式调用;而返回值不再为Stream
接口的为终结方法,不再支持链式调用。如下表所示:
方法名 | 方法作用 | 方法种类 | 是否支持链式调用 |
---|---|---|---|
count | 统计个数 | 终结 | 否 |
forEach | 逐一处理 | 终结 | 否 |
filter | 过滤 | 函数拼接 | 是 |
limit | 取用前几个 | 函数拼接 | 是 |
skip | 跳过前几个 | 函数拼接 | 是 |
map | 映射 | 函数拼接 | 是 |
concat | 组合 | 函数拼接 | 是 |
备注:本小节之外的更多方法,请自行参考API文档。
1).forEach方法:用于遍历
java
package com.itheima.demo03Stream;
import java.util.stream.Stream;
/*
Stream流中常用的方法
forEach:用于遍历Stream流中的元素
void forEach(Consumer<? super T> action) 对此流的每个元素执行操作。
参数:
Consumer<? super T> action:是一个消费型函数式接口,参数可以传递Lambda表达式
抽象方法:
void accept(T t) :消费一个指定泛型类型的数据
注意:
forEach方法是一个终结方法,没有返回值;也不能使用链式编程继续调用Stream流中的方法了
*/
public class Demo04forEach {
public static void main(String[] args) {
//获取Stream流
Stream<Integer> stream = Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
//使用forEach方法遍历Stream流中的元素
/*stream.forEach((Integer i)->{
System.out.println(i);
});*/
/*
IllegalStateException: stream has already been operated upon or closed
Stream流只能使用一次,使用完毕会流向下一个Stream对象
之前的Stream流对象就已经关闭了,被销毁了,所以就不能在使用了,会抛出非法状态异常
简化lambda表达式
*/
stream.forEach(i-> System.out.println(i));
}
}
2).count方法:统计个数
java
package com.itheima.demo03Stream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.stream.Stream;
/*
Stream流中常用的方法
count方法:统计个数
long count() 返回此流中的元素数。
注意:
count方法是一个终结方法,返回值类型是long;也不能使用链式编程继续调用Stream流中的方法了
*/
public class Demo05count {
public static void main(String[] args) {
//获取Stream流
Stream<Integer> stream = Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
long c1 = stream.count();
System.out.println(c1);//10
ArrayList<String> list = new ArrayList<>();
Collections.addAll(list,"aa","bb","cc","dd","ee");
//把集合转换为Stream流
Stream<String> stream2 = list.stream();
System.out.println(stream2.count());//5
}
}
3).filter方法:过滤
java
package com.itheima.demo03Stream;
import java.util.stream.Stream;
/*
Stream流中常用的方法
filter方法:用于过滤Stream流中的元素
Stream<T> filter(Predicate<? super T> predicate)
参数:
Predicate<? super T> predicate:函数式接口,参数可以传递Lambda表达式
抽象方法:
boolean test(T t) 用于对接口指定泛型类型的数据进行判断
注意:
filter方法返回值类型是Stream,是一个非终结方法,可以使用返回的Stream流对象继续调用Stream流中的其他方法(链式编程)
*/
public class Demo06filter {
public static void main(String[] args) {
//创建一个Stream流
Stream<String> stream1 = Stream.of("美羊羊", "喜羊羊", "懒羊羊", "沸羊羊",
"暖羊羊", "慢羊羊", "灰太狼", "红太狼", "小灰灰");
//使用filter方法过滤Stream流中的元素,只要包含羊羊的
//Stream<String> stream2 = stream1.filter((String s) -> {
// return s.contains("羊羊");
//});
//遍历stream2流对象
//stream2.forEach(s-> System.out.println(s));
//链式编程
stream1.filter(s->s.contains("羊羊")).forEach(s-> System.out.println(s));
}
}
4).limit方法:获取前n个元素
java
package com.itheima.demo03Stream;
import java.util.stream.Stream;
/*
Stream流中常用的方法
limit方法:获取前n个元素
Stream<T> limit(long maxSize) 返回由此流的元素组成的流,截短长度不能超过 maxSize 。
例如
limit(4) 获取流中的前4个元素,存储到一个新的Stream流中返回
注意:
1.获取的数据大于流的长度,返回流中所有元素
2.limit方法返回值类型是Stream,是一个非终结方法,可以使用返回的Stream流对象继续调用Stream流中的其他方法(链式编程)
*/
public class Demo07limit {
public static void main(String[] args) {
//创建一个Stream流
Stream<String> stream1 = Stream.of("美羊羊", "喜羊羊", "懒羊羊", "沸羊羊",
"暖羊羊", "慢羊羊", "灰太狼", "红太狼", "小灰灰");
//获取Stream流中前4个元素,存储到一个新的Stream流中返回
//Stream<String> stream2 = stream1.limit(4);
//stream2.forEach(s-> System.out.println(s));
//stream1.limit(4).forEach(s -> System.out.println(s));
//stream1.limit(11).forEach(s -> System.out.println(s));//9个
long count = stream1.limit(11).count();
System.out.println(count);
}
}
5).skip:跳过前n个元素
java
package com.itheima.demo03Stream;
import java.util.stream.Stream;
/*
Stream流中常用的方法
skip:跳过前n个元素
Stream<T> skip(long n)
注意:
1.skip跳过的元素数量大于流中元素的个数,返回一个没有元素的空流
2.skip方法返回值类型是Stream,是一个非终结方法,可以使用返回的Stream流对象继续调用Stream流中的其他方法(链式编程)
*/
public class Demo08skip {
public static void main(String[] args) {
//获取Stream流
Stream<Integer> stream = Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
//跳过前6个元素,把剩余的元素,存储到一个新的Stream流中返回
//Stream<Integer> stream1 = stream.skip(6);
//stream1.forEach(s-> System.out.println(s));//7,8,9,10
//stream.skip(6).forEach(s-> System.out.println(s));
System.out.println(stream.skip(11).count());//0 skip跳过的元素数量大于流中元素的个数,返回一个没有元素的空流
}
}
6).map方法:映射,类型转换
java
package com.itheima.demo03Stream;
import java.util.stream.Stream;
/*
Stream流中常用的方法
map方法:映射,类型转换
<R> Stream<R> map(Function<? super T,? extends R> mapper)
参数:
Function<T,R>:函数式接口,可以传递Lambda表达式
接口中唯一的抽象方法:
R apply(T t) 根据参数类型T获取类型R的接口,用于类型转换 T-->R
注意:
map方法返回值类型是Stream,是一个非终结方法,可以使用返回的Stream流对象继续调用Stream流中的其他方法(链式编程)
*/
public class Demo09map {
public static void main(String[] args) {
Stream<String> stream1 = Stream.of("11", "22", "33", "44");
//使用map方法,把字符串类型的Stream流,转换为Integer类型的Stream流返回
//Stream<Integer> stream2 = stream1.map((String s) -> {
// return Integer.parseInt(s);
//});
//遍历stream2流对象
//stream2.forEach(s-> System.out.println(s+10));
//链式编程
//stream1.map(s->Integer.parseInt(s)).forEach(s-> System.out.println(s));
Stream<String> stream3 = Stream.of("迪丽热巴", "杨幂", "柳岩");
//使用map方法,把字符串类型的Stream流,转换为Person类型的流返回
//Stream<Person> stream4 = stream3.map(s -> new Person(s));
//stream4.forEach(s-> System.out.println(s));
stream3.map(s->new Person(s)).forEach(p-> System.out.println(p));
}
}
7).concat方法:组合
java
package com.itheima.demo03Stream;
import java.io.Serializable;
import java.util.stream.Stream;
/*
Stream流中常用的方法
concat方法:组合,把两个Stream流,组合为一个新的Stream流
static <T> Stream<T> concat(Stream<? extends T> a, Stream<? extends T> b)
注意:
concat方法返回值类型是Stream,是一个非终结方法,可以使用返回的Stream流对象继续调用Stream流中的其他方法(链式编程)
*/
public class Demo10concat {
public static void main(String[] args) {
Stream<String> stream1 = Stream.of("美羊羊", "喜羊羊", "懒羊羊", "沸羊羊",
"暖羊羊", "慢羊羊", "灰太狼", "红太狼", "小灰灰");
Stream<String> stream2 = Stream.of("迪丽热巴", "杨幂", "柳岩");
//使用concat方法,把stream1和stream2组合为一个新的流
//Stream<String> concat = Stream.concat(stream1, stream2);
//遍历Stream流
//concat.forEach(s-> System.out.println(s));
Stream.concat(stream1,stream2).forEach(s-> System.out.println(s));
//Stream<Integer> stream3 = Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
//Stream<String> stream4 = Stream.of("11", "22", "33", "44");
//Stream<Object> stream5 = Stream.concat(stream3, stream4);
//System.out.println(stream5.count());//14
}
}
6.综合案例(练习)
1).不使用Stream流的方式
java
package com.itheima.demo04Stream;
import java.util.ArrayList;
import java.util.List;
/*
Stream流综合练习题
现在有两个 ArrayList 集合存储队伍当中的多个成员姓名,要求使用传统的for循环(或增强for循环)
依次进行以下若干操作步骤:
1. 第一个队伍只要名字为3个字的成员姓名,把3个字的成员姓名存储到一个新的集合中
2. 第一个队伍筛选之后只要前3个人,把前3个人存储到一个新的集合中
3. 第二个队伍只要姓张的成员姓名,把姓张的成员姓名存储到一个新的集合中
4. 第二个队伍筛选之后不要前2个人,跳过前2个人,把其余的人存储到一个新的集合中
5. 将两个队伍合并为一个队伍,把两个集合组合为一个新的集合
6. 根据姓名创建 Person 对象,把Person对象存储到一个新的集合中
7. 打印整个队伍的Person对象信息。
*/
public class Demo01StreamTest {
public static void main(String[] args) {
List<String> one = new ArrayList<>();
one.add("迪丽热巴");
one.add("宋远桥");
one.add("苏星河");
one.add("老子");
one.add("庄子");
one.add("孙子");
one.add("洪七公");
one.add("欧阳锋");
one.add("蔡徐坤");
//1. 第一个队伍只要名字为3个字的成员姓名,把3个字的成员姓名存储到一个新的集合中
List<String> one1 = new ArrayList<>();
for (String s : one) {
if(s.length()==3){
one1.add(s);
}
}
System.out.println(one1);//[宋远桥, 苏星河, 洪七公, 欧阳锋, 蔡徐坤]
//2. 第一个队伍筛选之后只要前3个人,把前3个人存储到一个新的集合中
List<String> one2 = new ArrayList<>();
for (int i = 0; i < 3; i++) {//i=0,1,2
one2.add(one1.get(i));
}
System.out.println(one2);//[宋远桥, 苏星河, 洪七公]
List<String> two = new ArrayList<>();
two.add("古力娜扎");
two.add("张无忌");
two.add("张三丰");
two.add("赵丽颖");
two.add("张二狗");
two.add("张天爱");
two.add("张三");
//3. 第二个队伍只要姓张的成员姓名,把姓张的成员姓名存储到一个新的集合中
List<String> two1 = new ArrayList<>();
for (String s : two) {
if(s.startsWith("张")){
two1.add(s);
}
}
System.out.println(two1);//[张无忌, 张三丰, 张二狗, 张天爱, 张三]
//4. 第二个队伍筛选之后不要前2个人,跳过前2个人,把其余的人存储到一个新的集合中
List<String> two2 = new ArrayList<>();
for (int i = 2; i <two1.size() ; i++) {
two2.add(two1.get(i));
}
System.out.println(two2);//[张二狗, 张天爱, 张三]
//5. 将两个队伍合并为一个队伍,把两个集合组合为一个新的集合
List<String> all = new ArrayList<>();
/*
Collection集合中的方法addAll
boolean addAll(Collection<? extends E> c) 将指定集合中的所有元素添加到此集合
*/
all.addAll(one2);
all.addAll(two2);
System.out.println(all);//[宋远桥, 苏星河, 洪七公, 张二狗, 张天爱, 张三]
//6. 根据姓名创建 Person 对象,把Person对象存储到一个新的集合中
List<Person> personList = new ArrayList<>();
for (String s : all) {
personList.add(new Person(s));
}
//7. 打印整个队伍的Person对象信息。
for (Person p : personList) {
System.out.println(p);
}
}
}
2).使用Stream流的方式
java
package com.itheima.demo04Stream;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Stream;
/*
Stream流综合练习题:使用Stream流的方式完成
现在有两个 ArrayList 集合存储队伍当中的多个成员姓名,要求使用传统的for循环(或增强for循环)
依次进行以下若干操作步骤:
1. 第一个队伍只要名字为3个字的成员姓名,把3个字的成员姓名存储到一个新的集合中
2. 第一个队伍筛选之后只要前3个人,把前3个人存储到一个新的集合中
3. 第二个队伍只要姓张的成员姓名,把姓张的成员姓名存储到一个新的集合中
4. 第二个队伍筛选之后不要前2个人,跳过前2个人,把其余的人存储到一个新的集合中
5. 将两个队伍合并为一个队伍,把两个集合组合为一个新的集合
6. 根据姓名创建 Person 对象,把Person对象存储到一个新的集合中
7. 打印整个队伍的Person对象信息。
*/
public class Demo02StreamTest {
public static void main(String[] args) {
List<String> one = new ArrayList<>();
one.add("迪丽热巴");
one.add("宋远桥");
one.add("苏星河");
one.add("老子");
one.add("庄子");
one.add("孙子");
one.add("洪七公");
one.add("欧阳锋");
one.add("蔡徐坤");
List<String> two = new ArrayList<>();
two.add("古力娜扎");
two.add("张无忌");
two.add("张三丰");
two.add("赵丽颖");
two.add("张二狗");
two.add("张天爱");
two.add("张三");
//1. 第一个队伍只要名字为3个字的成员姓名,把3个字的成员姓名存储到一个新的集合中
//2. 第一个队伍筛选之后只要前3个人,把前3个人存储到一个新的集合中
//把one集合转换为Stream流
Stream<String> oneStream = one.stream().filter(name -> name.length() == 3).limit(3);
//3. 第二个队伍只要姓张的成员姓名,把姓张的成员姓名存储到一个新的集合中
//4. 第二个队伍筛选之后不要前2个人,跳过前2个人,把其余的人存储到一个新的集合中
//把two集合转换为Stream流
Stream<String> twoStream = two.stream().filter(name -> name.startsWith("张")).skip(2);
//5. 将两个队伍合并为一个队伍,把两个集合组合为一个新的集合
//6. 根据姓名创建 Person 对象,把Person对象存储到一个新的集合中
//7. 打印整个队伍的Person对象信息。
Stream.concat(oneStream,twoStream).map(name->new Person(name)).forEach(s-> System.out.println(s));
}
}
7.收集Stream结果(重点)
把Stream流转换为集合或者把Stream流转换为数组
1).把Stream流转换为集合:收集到集合中
java
package com.itheima.demo05Stream;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/*
把Stream流转换为集合:收集到集合中
使用Stream流中的方法
R collect(Collector<?> collector) 把Stream流转换为集合
参数:
Collector是一个接口,需要传递接口的是实现类对象
java.util.stream.Collectors:是一个工具类,里边提供的静态方法,可以获取Collector接口的实现类对象
static <T> Collector<T,?,List<T>> toList() 返回一个 Collector ,将输入元素累加到一个新的 List 。
static <T> Collector<T,?,Set<T>> toSet() 返回一个 Collector ,将输入元素累加到一个新的 Set 。
*/
public class Demo01StreamToCollection {
public static void main(String[] args) {
Stream<String> stream1 = Stream.of("美羊羊", "喜羊羊", "懒羊羊", "沸羊羊",
"暖羊羊", "慢羊羊", "灰太狼", "红太狼", "小灰灰","灰太狼");
//把Stream流转换为List集合(有序,有索引,允许重复)
//List<String> list = stream1.collect(Collectors.toList());
//System.out.println(list);//[美羊羊, 喜羊羊, 懒羊羊, 沸羊羊, 暖羊羊, 慢羊羊, 灰太狼, 红太狼, 小灰灰, 灰太狼]
//把Stream流转换为Set集合(不包含带索引的方法,不允许存储重复元素)
Set<String> set = stream1.collect(Collectors.toSet());
System.out.println(set);//[美羊羊, 沸羊羊, 红太狼, 灰太狼, 暖羊羊, 小灰灰, 喜羊羊, 懒羊羊, 慢羊羊]
}
}
2).把Stream流转换为数组:收集到数组中
java
package com.itheima.demo05Stream;
import java.util.stream.Stream;
/*
把Stream流转换为数组:收集到数组中
Stream流中的方法:
Object[] toArray() 返回一个包含此流的元素的数组。
*/
public class Demo02StreamToArray {
public static void main(String[] args) {
Stream<String> stream1 = Stream.of("美羊羊", "喜羊羊", "懒羊羊", "沸羊羊",
"暖羊羊", "慢羊羊", "灰太狼", "红太狼", "小灰灰","灰太狼");
Object[] arr = stream1.toArray();
for (Object o : arr) {
System.out.println(o);
}
}
}