JAVA进阶知识点总结 8【方法引用、Stream流】
01.第三章:方法引用_什么是方法引用
1).什么是“方法引用”:指引用现有的方法代替Lambda表达式–当我们要写一个Lambda表达式做一些事情时,发现有些方法已经实现了我们要做的事,这时就可以使用“已实现的方法”来代替我们要写的“Lambda表达式”,这种形式叫:方法引用。
02.第三章:方法引用_示例_对象名—引用成员方法
03.第三章:方法引用_示例_类名—引用静态方法
04.第三章:方法引用_替代原则
1).正常情况:引用方法的形参、返回值类型必须同接口中抽象方法的形参、数据类型一致;
2).如果抽方法返回值,引用的方法必须也要有返回值;
如果抽象方法没有返回值,引用的方法可以有,也可以没有返回值;
3).被引用的方法的形参类型,要大于,等于抽象方法的形参类型;
被引用方法的返回值类型,要小于,等于抽象方法的返回值类型;
05.第三章:方法引用_示例_类—构造引用
1).无参:
2).有参构造:
06.第三章:方法引用_示例_数组—构造器引用
07.第三章:类名引用静态方法_练习:
1).定义一个接口:
public interface Animal {
public void show(String s);
}
2).测试类:
public class Demo {
public static void main(String[] args) {
//1.使用匿名内部类
fun(new Animal() {
@Override
public void show(String s) {
System.out.println("我是:" + s);
}
},"小猫...");
//2.使用Lambda
fun(s -> System.out.println("我是:" + s),"小狗...");
//3.使用方法:System.out属性PrintStream的println(String s);
fun(System.out::println, "小猪...");
}
public static void fun(Animal a,String s){
a.show(s);
}
}
08.第四章:Stream流_Stream流进行集合过滤的效果演示
1).什么是“Stream流”:它在Java中是一个接口,它类似于“迭代器”,但比迭代器更强大,
它也是对集合元素操作,但提供了比迭代器更丰富的功能:筛选、过滤、统计…。
2).Stream效果演示:
public class Demo {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("张无忌");
list.add("周芷若");
list.add("赵敏");
list.add("张强");
list.add("张三丰");
//1.找出所有"张"姓学员–存到一个新集合中
List<String> list1 = new ArrayList<>();
for(String s : list){
if(s.startsWith("张")){
list1.add(s);
}
}
//2.再筛选出名字是三个字的张姓学员–存到一个新集合中
List list2 = new ArrayList<>();
for(String s : list1){
if(s.length() == 3){
list2.add(s);
}
}
//3.打印最终结果
for (String s : list2) {
System.out.println(s);
}
//*******************使用Stream流***********************
list.stream().filter(s -> s.startsWith("张"))
.filter(s -> s.length() == 3)
.forEach(s -> System.out.println(s));
}
}
09.第四章:Stream流_流思想概述
1).“流”它就是一个增强的“迭代器”,可以对集合元素进行筛选、过滤、汇总…等操作。
10.第四章:Stream流_获取List_Set_Map_数组流
1).通过List和Set集合获取流:
List<String> list = new ArrayList<>();
...
Stream<String> sm = list.stream();
Set<String> set = new HashSet<>();
...
Stream<String> sm = set.stream();
2).通过Map集合获取流:
Map不能直接获取流:
Map<Integer,String> map = new HashMap<>();
....
1).获取所有键的流:
Stream<Integer> keyStream = map.keySet().stream();
2).获取所有值的流:
Stream<String> valueStream = map.values().stream();
3).获取所有键值对的流:
Stream<Map.Entry<Integer,String>> entryStream = map.entrySet().stream();
3).通过数组获取流:
1).引用类型数组:
Integer[] arr = {1,2,3,4,5};
Stream<Integer> intStream = Stream.of(arr);
2).基本类型数组:
int[] arr = {1,2,3,4,5};
IntStream stream = IntStream.of(arr);
4).通过一些零散的数据获取流:
Stream<Integer> stream = Stream.of(1,2,3,4,5);
11.第四章:Stream流_常用方法_逐一处理forEach
1).方法原型:
class Stream的子类{
list.add("张无忌");
list.add("周芷若");
list.add("赵敏");
list.add("张强");
list.add("张三丰");
void forEach(Consumer<T> action){
//1.遍历所有元素
for(String s : 所有元素){
action.accept(s);
}
}
}
2).示例代码:
public class Demo {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("张无忌");
list.add("周芷若");
list.add("赵敏");
list.add("张强");
list.add("张三丰");
List<String> list2 = new ArrayList<>();
//遍历所有元素
/*list.stream().forEach(new Consumer<String>() {
@Override
public void accept(String s) {
list2.add(s);
}
});*/
//使用Lambda
list.stream().forEach(s -> list2.add(s));
System.out.println(list2);
}
}
12.第四章:Stream流_常用方法_过滤filter
1).方法原型:
class Stream的子类{//伪代码
Stream<T> filter(Predicate<T> predicate){
//1.定义一个新流
Stream<T> newStream = new Stream的子类();
//2.遍历所有元素
for(String s : 所有元素){
boolean b = predicate.test(s);
if(b){
//将当前元素放到新流中
newStream.add(s);
}
}
//3.返回新流
return newStream;
}
}
2).示例代码:
public class Demo {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("张无忌");
list.add("周芷若");
list.add("赵敏");
list.add("张强");
list.add("张三丰");
//筛选出所有的张姓学员
/*list.stream().filter(new Predicate<String>() {
@Override
public boolean test(String s) {
return s.startsWith("张");
}
}).forEach(s-> System.out.println(s));*/
//使用Lambda
list.stream().filter(s->s.startsWith("张")).forEach(System.out::println);
}
}
13.第四章:Stream流_常用方法_统计个数count
1).原型:
long count():
2).示例代码:
public class Demo {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("张无忌");
list.add("周芷若");
list.add("赵敏");
list.add("张强");
list.add("张三丰");
long c = list.stream().filter(s -> s.startsWith("张")).count();
System.out.println("张姓学员的数量:" + c);
}
}
14.第二章:Stream流_常用方法_取用前几个limit
1).方法原型:
Stream limit(long maxSize);
2).示例代码:
public class Demo {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("张无忌");
list.add("周芷若");
list.add("赵敏");
list.add("张强");
list.add("张三丰");
//1.打印集合元素前三个:注意:不能是负数
list.stream().limit(30).forEach(System.out::println);
}
}
15.第二章:Stream流_常用方法_跳过前几个skip
1).方法原型:
Stream skip(long n);
2).示例代码:
public class Demo {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("张无忌");
list.add("周芷若");
list.add("赵敏");
list.add("张强");
list.add("张三丰");
//跳过前2个,注意:不能是负数
list.stream().skip(2).forEach(System.out::println);
}
}
16.第二章:Stream流_常用方法_映射(转换)map
1).原型:
Stream map(Function<T, R> mapper);
将一种泛型的Stream转换为另一种泛型
2).示例代码:
public class Demo {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("88");
list.add("76");
list.add("55");
list.add("44");
//将集合中每个分数 + 5 显示
//1.使用匿名内部类
Stream<Integer> intStream = list.stream().map(new Function<String, Integer>() {
@Override
public Integer apply(String s) {
return Integer.valueOf(s);
}
});
intStream.forEach(n -> System.out.println(n + 5));
System.out.println("---------------------------------------");
//2.使用Lambda表达式
list.stream().map(s -> Integer.valueOf(s)).forEach(n -> System.out.println(n + 5));
}
}
17.第二章:Stream流_常用方法_合并concat
1).方法原型:将两个Stream合成一个Stream
public static Stream concat(Stream a, Stream b)
2).示例代码:
public class Demo {
public static void main(String[] args) {
List<String> list1 = new ArrayList<>();
list1.add("张三丰");
list1.add("张无忌");
list1.add("张翠山");
List<String> list2 = new ArrayList<>();
list2.add("灭绝师太");
list2.add("周芷若");
list2.add("赵敏");
Stream<String> stream = Stream.concat(list1.stream(),list2.stream());
stream.forEach(System.out::println);
}
}
18.第二章:Stream流_练习_集合元素处理的Stream方式
public class Demo {
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("洪七公");
List<String> two = new ArrayList<>();
two.add("古力娜扎");
two.add("张无忌");
two.add("张三丰");
two.add("赵丽颖");
two.add("张二狗");
two.add("张天爱");
two.add("张三");
/*
1. 第一个队伍只要名字为3个字的成员姓名;
2. 第一个队伍筛选之后只要前3个人;
3. 第二个队伍只要姓张的成员姓名;
4. 第二个队伍筛选之后不要前2个人;
5. 将两个队伍合并为一个队伍;
6. 根据姓名创建 Person 对象;
7. 打印整个队伍的Person对象信息。
*/
//1. 第一个队伍只要名字为3个字的成员姓名;
List<String> one1 = new ArrayList<>();
for (String s : one) {
if (s.length() == 3) {
one1.add(s);
}
}
//2. 第一个队伍筛选之后只要前3个人;
List<String> one2 = new ArrayList<>();
for (int i = 0; i < 3; i++) {
one2.add(one1.get(i));
}
//3. 第二个队伍只要姓张的成员姓名;
List<String> two1 = new ArrayList<>();
for (String s : two) {
if(s.startsWith("张")){
two1.add(s);
}
}
//4. 第二个队伍筛选之后不要前2个人;
List<String> two2 = new ArrayList<>();
for (int i = 2; i < two1.size(); i++) {
two2.add(two1.get(i));
}
//5. 将两个队伍合并为一个队伍;
List<String> allList = new ArrayList<>();
allList.addAll(one2);
allList.addAll(two2);
//6. 根据姓名创建 Person 对象;
List<Person> perList = new ArrayList<>();
for (String s : allList) {
Person p = new Person(s);
perList.add(p);
}
//7. 打印整个队伍的Person对象信息。
for (Person p : perList) {
System.out.println(p);
}
//*********************使用Stream流*********************************//
Stream.concat(one.stream().filter(s -> s.length() == 3).limit(3),
two.stream().filter(s-> s.startsWith("张")).skip(2))
.map(Person::new)//相当于:map(s -> new Person(s))
.forEach(System.out::println);
}
}
19.第二章:Stream流_总结_拼接方法与终结方法
1).拼接方法:方法返回的是一个Stream流,可以继续调用流的方法。
2).终结方法:方法返回的是一个最终结果,不能再继续调用流的方法.
20.第二章:Stream流_常用方法_收集Stream结果collect方法
1).之前我们的操作都是在“流”中,但我们最终是希望将结果再存到一个集合中。这时就需要将流转换为集合。
2).示例代码:
public class Demo {
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("洪七公");
//取出所有名字为3个字的学员,并存储到一个新集合
//转为:List
List<String> list = one.stream()
.filter(s -> s.length() == 3).collect(Collectors.toList());
System.out.println(list);
//转为:Set
Set<String> set = one.stream()
.filter(s -> s.length() == 3).collect(Collectors.toSet());
System.out.println(set);
//转为:数组
Object[] objArray = one.stream().filter(s -> s.length() == 3).toArray();
System.out.println(Arrays.toString(objArray));
}
}
=================================================================
学习目标总结:
01.能够使用方法引用的常见引用方式
1).通过对象,引用成员方法:
fun(new Student()::catEat)
2).通过类名,引用静态方法:
fun(Teacher::dogEat);
3).构造方法引用:
1).无参:
fun(Cat::new);
2).有参:
fun(Cat::new,"小花");
4).数组构造的引用:
fun(int[]::new,10);
02.能够理解流与集合相比的优点
1).流的一些操作可以生成新流,这样就可以使用链式编程,方便编写。
03.能够通过集合、映射或数组方式获取流
1).List和Set:
Stream s = list.stream();
Stream s = set.stream();
2).Map:不能获取流:
1).键流:Stream<键类型> keyStream = map.keySet().stream();
2).值流:Stream<值类型> valueStream = map.values().stream();
3).键值对流:Stream<Map.Entry> entryStream = map.entrySet().stream()
3).数组:
1).引用类型数组:
Integer[] arr = {1,2,3};
Stream<Integer> stream = Stream.of(arr);
2).基本类型数组:
int[] arr = {1,2,3};
IntStream stream = IntStream.of(arr);
4).零散数据:
Stream<Integer> stream = Stream.of(1,2,3,32,432,4,32);
04.能够掌握常用的流操作
1).forEach():遍历
2).filter()获取
3).count():
4).limit()
5).skip():
6).map()
7).concat()
05.能够将流中的内容收集到集合中
List list = list.stream().filter(...).collect(Collectors.toList());
Set set = list.stream().filter(...).collect(Collectors.toSet());
06.能够将流中的内容收集到数组中
Object[] objArray = list.stream().filter(...).toArray();