一、Stream流
1.获取Stream流的方式
Stream (单列)集合.stream();
Stream Stream.of(容器);
注意事项:流对象只能用一次。如果多次使用,需要单独获取流对象
示例代码:
public class Demo01GetStream {
public static void main(String[] args) {
//把集合转换为Stream流
List<String> list = new ArrayList<>();
Stream<String> stream1 = list.stream();
Set<String> set = new HashSet<>();
Stream<String> stream2 = set.stream();
Map<String,String> map = new HashMap<>();
//获取键,存储到一个Set集合中
Set<String> keySet = map.keySet();
Stream<String> stream3 = keySet.stream();
//获取值,存储到一个Collection集合中
Collection<String> values = map.values();
Stream<String> stream4 = values.stream();
//获取键值对(键与值的映射关系 entrySet)
Set<Map.Entry<String, String>> entries = map.entrySet();
Stream<Map.Entry<String, String>> stream5 = entries.stream();
//把数组转换为Stream流
Stream<Integer> stream6 = Stream.of(1, 2, 3, 4, 5);
//可变参数可以传递数组
Integer[] arr = {1,2,3,4,5};
Stream<Integer> stream7 = Stream.of(arr);
String[] arr2 = {"a","bb","ccc"};
Stream<String> stream8 = Stream.of(arr2);
}
}
2.Stream流的常用方法-forEach
forEach(Consumer<T>); 用于遍历容器(终结方法)
示例代码:
public class Demo02Stream_forEach {
public static void main(String[] args) {
//获取一个Stream流
Stream<String> stream = Stream.of("张三", "李四", "王五", "赵六", "田七");
//使用Stream流中的方法forEach对Stream流中的数据进行遍历
stream.forEach(name->System.out.println(name));
System.out.println("=======================");
ArrayList<Integer> list = new ArrayList<>();
list.add(5);
list.add(4);
list.add(3);
list.add(2);
list.add(1);
//获取Stream流
Stream<Integer> stream2 = list.stream();
//遍历集合
stream2.forEach(i -> System.out.println(i));
}
}
3.Stream流的常用方法-filter
filter(Predicate<t>); 用于过滤条件(延迟方法)
示例代码:
public class Demo03Stream_filter {
public static void main(String[] args) {
//创建一个Stream流
Stream<String> stream = Stream.of("张三丰", "张翠山", "赵敏", "周芷若", "张无忌");
//对Stream流中的元素进行过滤,只要姓张的人
Stream<String> stream2 = stream.filter((String name)->{return name.startsWith("张");});
//遍历stream2流
stream2.forEach(name-> System.out.println(name));
System.out.println("========================");
ArrayList<Integer> list = new ArrayList<>();
list.add(5);
list.add(4);
list.add(3);
list.add(2);
list.add(1);
//只要集合中的偶数
Stream<Integer> stream3 = list.stream();
stream3.filter(num->num % 2 == 0).forEach(i-> System.out.println(i));
}
}
4.Stream流的常用方法-map
map(Function<T,R>); 用于数据类型转换(延迟方法)
示例代码:
public class Demo04Stream_map {
public static void main(String[] args) {
//获取一个String类型的Stream流
Stream<String> stream = Stream.of("1", "2", "3", "4");
//使用map方法,把字符串类型的整数,转换(映射)为Integer类型的整数
Stream<Integer> stream2 = stream.map((String s)->{
return Integer.parseInt(s);
});
//遍历Stream2流
stream2.forEach(i-> System.out.println(i));
System.out.println("====================");
ArrayList<Integer> list = new ArrayList<>();
list.add(5555);
list.add(44);
list.add(3);
list.add(22222);
list.add(1111);
//通过Stream流完成:1将集合中的数字转成字符串类型的数字。2将字符串类型的数字长度大于3的保存到一个流中。3进行遍历
Stream<Integer> stream3 = list.stream();
stream3.map(i->i + "").filter(s->s.length() >= 3).forEach(num->System.out.println(num));
}
}
5.Stream流的常用方法-count
long count(); 获取流中的数据个数(终结方法)
示例代码:
public class Demo05Stream_count {
public static void main(String[] args) {
//获取一个Stream流
ArrayList<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);
list.add(4);
list.add(5);
list.add(6);
list.add(7);
Stream<Integer> stream = list.stream();
long count = stream.count();
System.out.println(count);//7
System.out.println("============");
ArrayList<Integer> list2 = new ArrayList<>();
list2.add(5555);
list2.add(44);
list2.add(3);
list2.add(22222);
list2.add(1111);
//通过Stream流完成:1将集合中的数字转成字符串类型的数字。2将字符串类型的数字长度大于3的保存到一个流中。3统计满足条件的元素个数
Stream<Integer> stream3 = list2.stream();
long count2 = stream3.map(i->i + "").filter(s->s.length() >= 3).count();
System.out.println(count2);
}
}
6.Stream流的常用方法-limit
limit(long num); 截取指定个数的元素(延迟方法)
示例代码:
public class Demo06Stream_limit {
public static void main(String[] args) {
//获取一个Stream流
String[] arr = {"美羊羊","喜洋洋","懒洋洋","灰太狼","红太狼"};
Stream<String> stream = Stream.of(arr);
//使用limit对Stream流中的元素进行截取,只要前3个元素
Stream<String> stream2 = stream.limit(3);
//遍历stream2流
stream2.forEach(name-> System.out.println(name));
System.out.println("=============");
ArrayList<Integer> list2 = new ArrayList<>();
list2.add(5555);
list2.add(44);
list2.add(3);
list2.add(22222);
list2.add(1111);
//通过Stream流完成:1将集合中的数字转成字符串类型的数字。
// 2将字符串类型的数字长度大于3的保存到一个流中。3将长度为3的字符串数字只需要保存前两个元素。4遍历
Stream<Integer> stream3 = list2.stream();
stream3.map(i->i + "").filter(s->s.length() >= 3).limit(2).forEach(s-> System.out.println(s));
}
}
7.Stream流的常用方法-skip
skip(long num); 跳过指定的元素个数(延迟方法)
示例代码:
public class Demo07Stream_skip {
public static void main(String[] args) {
//获取一个Stream流
String[] arr = {"美羊羊","喜洋洋","懒洋洋","灰太狼","红太狼"};
Stream<String> stream = Stream.of(arr);
//使用skip方法跳过前3个元素
Stream<String> stream2 = stream.skip(3);
//遍历stream2流
stream2.forEach(name-> System.out.println(name));
System.out.println("===============");
ArrayList<Integer> list2 = new ArrayList<>();
list2.add(5555);
list2.add(44);
list2.add(3);
list2.add(22222);
list2.add(1111);
//通过Stream流完成:1将集合中的数字转成字符串类型的数字。
// 2将字符串类型的数字长度大于3的保存到一个流中。3将长度为3的字符串数字只需要保存前两个元素。
// 4将之前保留了前两个元素的流中,跳过第一个。 5遍历
Stream<Integer> stream3 = list2.stream();
stream3.map(i->i + "").filter(s->s.length() >= 3).limit(2).skip(1).forEach(s-> System.out.println(s));
}
}
8.Stream流的常用方法-concat
concat(Stream1,Stream2); 将多个流对象拼接(延迟方法)
示例代码:
public class Demo08Stream_concat {
public static void main(String[] args) {
//创建一个Stream流
Stream<String> stream1 = Stream.of("张三丰", "张翠山", "赵敏", "周芷若", "张无忌");
//获取一个Stream流
String[] arr = {"美羊羊","喜洋洋","懒洋洋","灰太狼","红太狼"};
Stream<String> stream2 = Stream.of(arr);
//把以上两个流组合为一个流
Stream<String> concat = Stream.concat(stream1, stream2);
//遍历concat流
concat.forEach(name-> System.out.println(name));
}
}
9.集合的案例-传统方式
略~
10.集合的案例-Stream流的方式
public class Demo02StreamTest {
public static void main(String[] args) {
//第一支队伍
ArrayList<String> one = new ArrayList<>();
one.add("迪丽热巴");
one.add("宋远桥");
one.add("苏星河");
one.add("石破天");
one.add("石中玉");
one.add("老子");
one.add("庄子");
one.add("洪七公");
//1. 第一个队伍只要名字为3个字的成员姓名;存储到一个新集合中。
//2. 第一个队伍筛选之后只要前3个人;存储到一个新集合中。
Stream<String> oneStream = one.stream().filter(name -> name.length() == 3).limit(3);
//第二支队伍
ArrayList<String> two = new ArrayList<>();
two.add("古力娜扎");
two.add("张无忌");
two.add("赵丽颖");
two.add("张三丰");
two.add("尼古拉斯赵四");
two.add("张天爱");
two.add("张二狗");
//3. 第二个队伍只要姓张的成员姓名;存储到一个新集合中。
//4. 第二个队伍筛选之后不要前2个人;存储到一个新集合中。
Stream<String> twoStream = two.stream().filter(name -> name.startsWith("张")).skip(2);
//5. 将两个队伍合并为一个队伍;存储到一个新集合中。
//6. 根据姓名创建Person对象;存储到一个新集合中。
//7. 打印整个队伍的Person对象信息。
Stream.concat(oneStream,twoStream).map(name->new Person(name)).forEach(p-> System.out.println(p));
}
}
二、方法引用
1.使用格式
调用方法(对象::方法名);
2.格式解释
调用方法(需要传递一个对象::一个该对象中的具体方法名);
等效于:
重写了抽象方法,在方法体中,去执行传递过来的那个对象中的具体的方法
3.示例代码:
public class Demo01Printable {
//定义一个方法,参数传递Printable接口,对字符串进行打印
public static void printString(Printable p){
p.print("HelloWorld");
}
public static void main(String[] args) {
//调用printString方法,方法的参数Printable是一个函数式接口,所以可以传递Lambda
printString((String s)->{
System.out.println(s);
});
/*
分析:
Lambda表达式的目的,打印参数传递的字符串
把参数s,传递给了System.out对象,调用out对象中的方法println对字符串进行了输出
注意:
1.System.out对象是已经存在的
2.println方法也是已经存在的
所以我们可以使用方法引用来优化Lambda表达式
可以使用System.out方法直接引用(调用)println方法
*/
printString(System.out::println);
}
}
4.对象的方法引用
public class Demo01ObjectMethodReference {
//定义一个方法,方法的参数传递Printable接口
public static void printString(Printable p){
p.print("Hello");
}
public static void main(String[] args) {
//调用printString方法,方法的参数Printable是一个函数式接口,所以可以传递Lambda表达式
printString((String s)->{
//创建MethodRerObject对象
MethodRerObject obj = new MethodRerObject();
//调用MethodRerObject对象中的成员方法printUpperCaseString,把字符串按照大写输出
obj.printUpperCaseString(s);
});
/*
使用方法引用优化Lambda
对象是已经存在的MethodRerObject
成员方法也是已经存在的printUpperCaseString
所以我们可以使用对象名引用成员方法
*/
//创建MethodRerObject对象
MethodRerObject obj = new MethodRerObject();
printString(obj::printUpperCaseString);
}
}
5.静态方法引用
格式:调用方法(类名::方法名);
示例代码:
public class Demo01StaticMethodReference {
//定义一个方法,方法的参数传递要计算绝对值的整数,和函数式接口Calcable
public static int method(int number,Calcable c){
return c.calcAbs(number);
}
public static void main(String[] args) {
//调用method方法,传递计算绝对值得整数,和Lambda表达式
int number = method(-10,(int n)->{
//对参数进行绝对值得计算并返回结果
return Math.abs(n);
});
System.out.println(number);
/*
使用方法引用优化Lambda表达式
Math类是存在的
abs计算绝对值的静态方法也是已经存在的
所以我们可以直接通过类名引用静态方法
*/
int number2 = method(-10,Math::abs);
System.out.println(number2);
}
}
6.引用子父类关系的父类方法
格式:调用方法(super::方法名);
示例代码:
public class Man extends Human{
//子类重写父类sayHello的方法
@Override
public void sayHello() {
System.out.println("Hello 我是Man!");
}
//定义一个方法参数传递Greetable接口
public void method(Greetable g){
g.greet();
}
public void show(){
/*
使用super引用类的成员方法
super是已经存在的
父类的成员方法sayHello也是已经存在的
所以我们可以直接使用super引用父类的成员方法
*/
method(super::sayHello);
}
public static void main(String[] args) {
new Man().show();
}
}
7.引用本类的方法
格式:调用方法(this::方法名);
示例代码:
public class Husband {
//定义一个买房子的方法
public void buyHouse(){
System.out.println("北京二环内买一套四合院!");
}
//定义一个结婚的方法,参数传递Richable接口
public void marry(Richable r){
r.buy();
}
//定义一个非常高兴的方法
public void soHappy(){
//调用结婚的方法,方法的参数Richable是一个函数式接口,传递Lambda表达式
/* marry(()->{
//使用this.成员方法,调用本类买房子的方法
this.buyHouse();
});*/
/*
使用方法引用优化Lambda表达式
this是已经存在的
本类的成员方法buyHouse也是已经存在的
所以我们可以直接使用this引用本类的成员方法buyHouse
*/
marry(this::buyHouse);
}
public static void main(String[] args) {
new Husband().soHappy();
}
}
8.引用构造方法
格式:调用方法(对象::new);
示例代码:
public class Demo {
//定义一个方法,参数传递姓名和PersonBuilder接口,方法中通过姓名创建Person对象
public static void printName(String name,PersonBuilder pb){
Person person = pb.builderPerson(name);
System.out.println(person.getName());
}
public static void main(String[] args) {
//调用printName方法,方法的参数PersonBuilder接口是一个函数式接口,可以传递Lambda
printName("迪丽热巴",(String name)->{
return new Person(name);
});
/*
使用方法引用优化Lambda表达式
构造方法new Person(String name) 已知
创建对象已知 new
就可以使用Person引用new创建对象
*/
printName("古力娜扎",Person::new);//使用Person类的带参构造方法,通过传递的姓名创建对象
}
}
9.引用数组构造方法
格式:调用方法(数组::new);
示例代码:
public class Demo {
/*
定义一个方法
方法的参数传递创建数组的长度和ArrayBuilder接口
方法内部根据传递的长度使用ArrayBuilder中的方法创建数组并返回
*/
public static int[] createArray(int length, ArrayBuilder ab){
return ab.builderArray(length);
}
public static void main(String[] args) {
//调用createArray方法,传递数组的长度和Lambda表达式
int[] arr1 = createArray(10,(len)->{
//根据数组的长度,创建数组并返回
return new int[len];
});
System.out.println(arr1.length);//10
/*
使用方法引用优化Lambda表达式
已知创建的就是int[]数组
数组的长度也是已知的
就可以使用方法引用
int[]引用new,根据参数传递的长度来创建数组
*/
int[] arr2 =createArray(10,int[]::new);
System.out.println(Arrays.toString(arr2));
System.out.println(arr2.length);//10
}
}
函数式编程、方法引用、Lambda表达式【总结】
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.