目录
方法引用
在Lamda新特性的支持下,JAVA8中可以使用lamda表达式来创建匿名方法。然而,有时候我们仅仅是需要调用一个已存在的方法(如java中已经定义好的方法),在这时候java8新特性“方法引用”将会进一步简化操作(注意:需要有Lamda的支持)。
• 定义一个方法获取供给型接口类型的参数,调用 get 方法获取返回对象,并执行普通方法
示例
接口
package part4;
/**
* @date : 2022/11/23 9:36
*/
@FunctionalInterface
public interface PersonInterface {
public static final String name = "tidy";
public static final Integer age =18;
public void methodA();
}
类
package part4;
/**
* @date : 2022/11/23 9:31
*/
public class Person {
String name;
Integer age;
public static int method1() {
System.out.println("static静态方法...");
return 0;
}
public static int method2(int a) {
System.out.println("static静态方法..."+a);
return 0;
}
public Person() {
}
public Person(String name, Integer age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
测试类
package part4;
import java.util.ArrayList;
import java.util.List;
import java.util.function.BiFunction;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;
/**
* @date : 2022/11/23 9:29
*/
public class MethodReferenceDemo {
public static void main(String[] args) {
/* 方法引用的四种形式:
引用静态方法-->类名称::static 方法名称;
引用某个对象的实例的普通方法-->实例化对象::普通方法;
引用特定类型的任意对象的实例方法-->特定类::普通方法;
引用构造方法-->类名称::new
*/
// 1)引用构造方法-->类名称::new
/*Person person = new Person();
System.out.println(person);*/
// 注意事项1:方法引用 前提要使用lambda表达式--》功能性函数
// Person person = Person::new;
// 注意事项2:接口中没有构造方法 调用不成
// PersonInterface personInterface = PersonInterface::new;
// 借助于供给型接口 实例化对象
Supplier<Person> supplier = Person::new;
Person person = supplier.get();
System.out.println(person);
// 2) 引用静态方法-->类名称::static 方法名称;
Supplier<Integer> method1 = Person::method1;
Integer result = method1.get();
System.out.println("result:"+result);
System.out.println("==================");
// 调用静态方法时:选定和这个静态方法相匹配的功能性函数(是否匹配:是否有参数 是否有返回值--》使用哪个功能性函数)
Function<Integer,Integer> function = Person::method2;
Integer apply = function.apply(66);
System.out.println("applay:"+apply);
System.out.println("==================");
// 3)引用某个对象的实例的普通方法-->实例化对象::普通方法;
Person person1 = new Person("tidy",18);
Supplier<String> stringSupplier =person1::getName;
String name = stringSupplier.get();
System.out.println("name:"+name);
// 4)引用特定类型的任意对象的实例方法-->特定类::普通方法;
// String equals方法 比较两个字符串是否相等 2个字符串
// BiFunction
BiFunction<String,String,Boolean> biFunction = String::equals;
Boolean resultFlg = biFunction.apply("hello", "hello");
System.out.println("resultFlg:"+resultFlg);
System.out.println("6666666666666666666:");
List<Integer> list = new ArrayList();
list.add(10);
list.add(30);
list.add(30);
// 内部类
/* Consumer<Integer> consumer = new Consumer<Integer>() {
@Override
public void accept(Integer integer) {
System.out.println(integer);
}
};
list.forEach(consumer);*/
/*list.forEach(new Consumer<Integer>() {
@Override
public void accept(Integer integer) {
System.out.println(integer);
}
});*/
// list.forEach(t-> System.out.println(t));
// println(..):有参数没有返回值
/*Consumer consumer = System.out::println;
// 方法引用
list.forEach(consumer);*/
list.forEach(System.out::println);
}
}
Stream
Stream 的操作三个步骤
创建 Stream :一个数据源(如:集合、数组),获取一个流
中间操作 :一个中间操作链,对数据源的数据进行处理
终止操作(终端操作) :一个终止操作,执行中间操作链,并产生结果
创建 Stream 的 4 种方法
•通过Collection中的steam()方法创建流•通过Collection中的parallelSteam()方法创建流•通过Arrays中的steam()方法创建流•通过Stream中的of()静态方法创建流•通过Stream中的iterate()方法创建流•通过Steam中的generate()方法创建流
常见Stream接口的继承关系
Stream的中间操作
多个中间操作可以连接起来形成一个流水线,除非流水线上触发终止操作,否则中间操作不会执行任何的处理而在终止操作时一次性全部处理,称为“惰性求值”。
上面这个例子主要是对一组String数据进行操作,主要涉及到的中间操作方法有filter(),limit(),skip(),distinct()终止操作方法有forEach(),下面我们对这些常用方法进行简单介绍
中间操作常用方法
分类 | 方法 | 描述 |
筛选和切片 | filter(Predicate p) | 接收Lambda,从流中排除某些元素 |
limit(long maxSize) | 截断流,使其元素不超过给定数量 | |
skip(long n) | 跳过元素,返回一个跳过前n个元素的流。若流中元素不足n个,则返回一个空流。与limit(n)互补 | |
distinct() | 筛选,通过流所生成元素的hashCode()和equals()去除重复元素 | |
映射 | map(Function f) | 接收一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新的元素 |
mapToDouble(ToDoubleFunction f) | 接收一个函数作为参数,该函数会被应用到每个元素上,产生一个新的DoubleStream | |
mapTolnt(ToIntFunction f) | 同上 | |
mapToLong(ToLongFunction f) | 同上 | |
flatMap(Function f) | 接收一个函数作为参数,将流中的每一个值都换成另一个流,然后把所有流连接成一个流 | |
排序 | sorted() | 产生一个新流,其中按自然顺序排序 |
sorted(Comparator c) | 产生一个新流,其中按比较器顺序排序 |
Stream的终止操作
分类 | 方法 | 描述 |
查找与匹配 | allMatch(Predicate p) | 检查是否匹配所有元素 |
anyMatch(Predicate p) | 检查是否至少匹配一个元素 | |
findFirst() | 检查是否没有匹配所有元素返回第一个元素 | |
findAny() | 返回当前流中的任意元素 | |
count() | 返回流中元素总数 | |
max(Comparator c) | 返回流中最大值 | |
min(Comparator c) | 返回流中最小值 | |
forEach() | 内部迭代 | |
归约 | reduce(T iden, BinaryOperator b) | 可以将流中元素反复结合起来,得到一个值。返回T |
reduce(BinaryOperator b) | 可以将流中元素反复结合起来,得到一个值。返回 Optional | |
收集 | collect(Collector c) | 将流转换为其他形式。接收一个 Collector 接口的实现,用于给 Stream 中元素做汇总的方法 |
演示
Stream的终止操作-collect()
Collector 接口中方法的实现决定了如何对流执行收集操作(如收集到 List、Set/Map)。但是 Collectors 实用类提供了很多静态方法,可以方便地创建常见收集器实例,具体方法与实例如下表:
方法 | 返回类型 | 作用 |
toList | List | 把流中元素收集到 List |
toSet | Set | 把流中元素收集到 Set |
toCollection | Collection | 把流中元素收集到 Collection |
counting | Long | 计算流中元素的个数 |
summingInt | Integer | 对流中元素的整数属性求和 |
averagingInt | Double | 计算流中元素Integer属性的平均值 |
summarizingInt | IntSummaryStatistics | 收集流中Integer属性的统计值,如:平均值 |
joining | String | 连接流中每个字符串 |
maxBy | Optional | 根据比较器选择最大值 |
minBy | Optional | 根据比较器选择最小值 |
reducing | 归约产生的类型 | 收集流中Integer属性的统计值,如:平均值 |
collectingAndThen | 转换函数返回的类型 | 包裹另一个收集器,对其结果转换函数 |
groupingBy | Map<K, List> | 根据某属性值对流分组,属性为K,结果为V |
partitioningBy | Map<Boolean, List> | 根据true或false进行分区 |
示例代码演示
package part5;
import org.junit.Test;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
* @date : 2022/11/23 14:30
*/
public class JunitStream {
/**
* 数据源(集合、数组、变量、字符串。。。)---》Stream流对象
* 1、创建Stream流对象
*/
@Test
public void createStream() {
// list1数据源
List<Integer> list1 = new ArrayList<>();
list1.add(10);
list1.add(30);
list1.add(20);
// 1)集合对象中 stream()
Stream<Integer> stream = list1.stream();
stream.forEach(t -> System.out.println(t));
// 2)集合中方式2
Stream<Integer> stream2 = list1.parallelStream();
stream2.forEach(t -> System.out.println(t));
// 3)数组数据源--》Stream
Integer[] arr = {1, 3, 5, 7};
Stream<Integer> stream3 = Arrays.stream(arr);
// 4)Stream中的of方法
Stream<Integer> stream4 = Stream.of(1, 2, 3, 4, 5);
stream4.forEach(t-> System.out.println(t));
// 5)Stream中iterate
// 数据进行计算:从0开始 让他每次+2 :0 2 4 6 8 10.....
// iterate无限流
// Stream<Integer> stream5 = Stream.iterate(0, t -> t + 2);
// limit(3) 获取前3个数据
Stream<Integer> stream6 = Stream.iterate(0, t -> t + 2).limit(3);
stream6.forEach(t -> System.out.println(t));
System.out.println("===================");
// 6)Stream.generate
// Math.random()--double
// Stream.generate(()->{return Math.random();});
// Stream.generate(()-> Math.random());
// Stream<Double> generate = Stream.generate(Math::random);
Stream<Double> stream7 = Stream.generate(Math::random).limit(2);
stream7.forEach(t -> System.out.println(t));
// stream7.forEach(System.out::println);
}
/**
* 2、流操作:
* 中间操作
*/
@Test
public void operation() {
Stream<String> stream = Stream.of("Tom", ",", "Hello", " ", "Hello", "World");
// 1)中间操作-->新Stream流
// filter:过滤流 返回true条件都会添加到这个新流当中
Stream<String> newStream = stream.filter(str -> {
if (",".equals(str)) {
return false;
} else {
return true;
}
});
newStream.forEach(t -> System.out.println(t));
System.out.println("---------------------------");
Stream<String> stream2 = Stream.of("Tom", ",", "Hello", " ", "Hello", "World");
// 中间操作--limit 获取前X个数据
Stream<String> newStream2 = stream2.limit(2);
newStream2.forEach(t -> System.out.println(t));
System.out.println("------1111111111----------------------------");
Stream<String> stream3 = Stream.of("Tom", ",", "Hello", " ", "Hello", "World");
// 中间操作---skip跳过前多少个数据
Stream<String> streamNew = stream3.skip(2);
streamNew.forEach(t -> System.out.println(t));
System.out.println("----distict:-----------------------------");
Stream<Integer> streamDistinct = Stream.of(10, 20, 30, 10, 5);
// 中间操作去重--distinct
Stream<Integer> newDistinctStream = streamDistinct.distinct();
newDistinctStream.forEach(t -> System.out.println(t));
// 数组 1,3,7,8,9,2,4,7,2----去重后求其数据个数
Integer[] arr2 = {1, 3, 7, 8, 9, 2, 4, 7, 2};
Stream<Integer> stream1 = Arrays.stream(arr2);
long count = stream1.distinct().count();
System.out.println("count:" + count);
Stream<String> stream4 = Stream.of("Tom", ",", "Hello", " ", "Hello", "World");
// Stream<String> count1 = stream.filter(str -> !",".equals(str) ? true : false).limit(3).skip(1).distinct();
// 中间流 可以使用连续操作---链式编程
long count1 = stream4.filter(str -> !",".equals(str) ? true : false).limit(3).skip(1).distinct().count();
System.out.println("count1:" + count1);
System.out.println("=========sorted=============");
Integer[] arr = {1, 3, 7, 8, 9, 2, 4, 7, 2};
// 使用流的操作:数组去重 按照升序进行输出
Stream<Integer> stream5 = Arrays.stream(arr);
// 按照升序进行输出
// stream5.distinct().sorted().forEach(t-> System.out.println(t));
// 降序进行输出
stream5.distinct().sorted((a1, a2) -> a2.compareTo(a1)).forEach(t -> System.out.println(t));
System.out.println("flatMap:===================");
// 需求:"e", "d", "c", "a", "f", "b"--->"edcafb"
Stream<String> stream6 = Stream.of("e", "d", "c", "a", "f", "b");
stream6.flatMap(t -> Stream.of(t)).forEach(t -> System.out.print(t));
System.out.println("=============================");
Integer[] arr66 = {1, 3, 7, 8, 9, 2, 4, 7, 2, 60, 70};
// 分类:>=10归为一类数据 ----》999 <10归为两类----》0
Stream<Integer> stream66 = Arrays.stream(arr66);
Stream<Integer> stream661 = stream66.map(t -> t >= 10 ? 999 : 0);
stream661.forEach(t -> System.out.println(t));
}
/**
* 流操作注意事项:
* Stream 自己不会存储元素----》:数据源--》转换为流
* Stream 不会改变源对象。相反,他们会返回一个持有结果的新 Stream
* Stream 操作是延迟执行的。这意味着他们会等到需要结果的时候才执行
* Stream 只能被"消费"一次,一旦遍历过就会失效,就像容器的迭代器那样,想要再次遍历必须重新生成。
*/
@Test
public void operation2() {
Integer[] arr = {1, 3, 7, 8, 9, 2, 4, 7, 2};
Stream<Integer> stream = Arrays.stream(arr);
/*Stream<Integer> stream = Arrays.stream(arr);
Stream<Integer> newStream = stream.skip(2).distinct();
long count = newStream.count();*/
// Stream 只能被"消费"一次,一旦遍历过就会失效
stream.forEach(t -> System.out.println(t));
// java.lang.IllegalStateException: stream has already been operated upon or closed
long count = stream.distinct().count();
}
/**
* 2、流操作:
* 终止操作
*/
@Test
public void operation3() {
// Integer[] arr = {11, 3, 17};
// Stream<Integer> stream = Arrays.stream(arr);
// 判断数组中至少含有一个大于10数据
// anyMatch:至少含有一个
/* boolean result1 = stream.anyMatch(t -> t > 10);
System.out.println("result1:"+result1);*/
// 判断数组中所有的数据都大于5 true
/* boolean resultALl = stream.allMatch(t -> t >5);
System.out.println("resultALl:"+resultALl);*/
// 求 数组中所有元素之和
/* Optional<Integer> reduce = stream.reduce((num1, num2) -> num1 + num2);
Integer sum = reduce.get();
System.out.println("sum:"+sum);*/
// 求 数组中所有数据乘积
/*Optional<Integer> reduce2 = stream.reduce((num1, num2) -> num1 * num2);
Integer result = reduce2.get();
System.out.println("result:"+result);
Stream<String> streamNew = Stream.of("a", "b", "c");
Optional<String> reduce3 = streamNew.reduce((str1, str2) -> str1 + str2);
String str = reduce3.get();
System.out.println(str);*/
/* Integer[] arr1 = {1, 2, 3, 4, 5};
Stream<Integer> stream1 = Arrays.stream(arr1);
// 求 数组中所有奇数和
Optional<Integer> reduce7 = stream1.filter(t -> t % 2 != 0).reduce((a, b) -> a + b);
Integer result77 = reduce7.get();
System.out.println(result77);*/
// System.out.println("=======collect:=流--》集合对象转换===============");
/*Stream<String> stream2 = Stream.of("e", "d", "c", "a", "f", "b"); //把流中元素收集到
List<String> list = stream2.collect(Collectors.toList()); // 调用终止操作的方法后需要重新定义
Stream stream = Stream.of("e", "d", "c", "a", "f", "b"); // 把流中元素收集到
Set<String> set = stream2.collect(Collectors.toSet());
stream = Stream.of("e", "d", "c", "a", "f", "b");
// 把流中元素收集到 Collection(ArrayList)
// ArrayList::new 等同于()->new ArrayList()
// ArrayList::new 可以是list,set接口下的任意实现类
ArrayList<String> alist = stream2.collect(Collectors.toCollection(ArrayList::new));
System.out.println(list); // [e, d, c, a, f, b]
System.out.println(set); // [a, b, c, d, e, f]
System.out.println(alist); // [e, d, c, a, f, b]
*/
System.out.println("====collect===Collectors:功能===============");
Integer[] arr2 = {1, 2, 3, 4, 5};
Stream<Integer> stream1 = Arrays.stream(arr2);
// 计数
/*Long count = stream1.collect(Collectors.counting());
System.out.println("count:"+count);*/
// 求和
Integer sum = stream1.collect(Collectors.summingInt(t -> t));
System.out.println("sum:"+sum);
System.out.println("========================");
// groupingBy: 分班 java314 精英班 成绩要求都是80分(含)以上 80分以下分数---java00
Integer[] scores = {85, 90, 100, 70, 80,75};
// java314---》 85 90 100 80
// java00--->70 75
Stream<Integer> stream = Arrays.stream(scores);
Map<String, List<Integer>> map = stream.collect(Collectors.groupingBy(t -> t >= 80 ? "java314" : "java00"));
map.forEach((k,v)-> System.out.println(k+"----"+v));
}
}
作业
package part5;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
* @author : cqq
* @date : 2022/11/23 13:13
*/
public class Task {
public static void main(String[] args) {
// 1. 给一个整数集合,分别求集合中偶数和与奇数和
List<Integer> list1 = new ArrayList<>();
list1.add(1);
list1.add(2);
list1.add(3);
list1.add(4);
list1.add(5);
list1.add(6);
list1.add(7);
list1.add(8);
list1.add(9);
list1.add(10);
// list1.stream().filter(t->t%2==0).forEach(a-> System.out.println(a));
Optional<Integer> reduce = list1.stream().filter(t -> t % 2 == 0).reduce((x, y) -> x + y);
Integer ou = reduce.get();
System.out.println("ou和:"+ou);
// list1.stream().filter(t->t%2!=0).forEach(a-> System.out.println(a));
Optional<Integer> ji = list1.stream().filter(t -> t % 2 != 0).reduce((x, y) -> x + y);
System.out.println("ji和:"+ji.get());
//
//
//
//
//
System.out.println("---------------------");
// 2. 给一个整数集合,将集合分成偶数集合和奇数集合
ArrayList<Integer> li = new ArrayList<>();
li.add(1);
li.add(2);
li.add(3);
li.add(4);
li.add(5);
li.add(6);
List<Integer> ou1 = li.stream().filter(t->t%2==0).collect(Collectors.toList());
System.out.println("ou:"+ou1);
List<Integer> ji1 = li.stream().filter(t->t%2!=0).collect(Collectors.toList());
System.out.println("ji:"+ji1);
/*// List<Integer> list22 = list1.stream().filter(t -> t % 2 == 0).collect(Collectors.toList());
List<String> list66 = list1.stream().map(t -> t + "").collect(Collectors.toList());
System.out.println(list66);
System.out.println("---------888888888888------------");
List list7 = new ArrayList<>();
list7.add("hello");
list7.add(2);
System.out.println(list7);
System.out.println("===========999999999:=============");
//
//*/
//
// 3. 集合转换:[[1, 2, 3, 4, 5], [2, 1, 9, 3, 6, 7], [3, 1, 6]] -> ["1", "2", "4", "5", "2", …… "3", "1","6"]
List<Integer> list4 = new ArrayList<>();
List<Integer> list2 = new ArrayList<>();
List<Integer> list3 = new ArrayList<>();
Collections.addAll(list4,1,2,3,4,5);
Collections.addAll(list2,3,1,6);
Collections.addAll(list3,2,1,9,3,6,7);
List<String> list = new ArrayList<>();
list1.stream().map(t -> list.add("“"+t+"”")).collect(Collectors.toList());
list2.stream().map(t -> list.add("“"+t+"”")).collect(Collectors.toList());
list3.stream().map(t -> list.add("“"+t+"”")).collect(Collectors.toList());
System.out.println(list);
/* List<Integer> list99 = new ArrayList<>();
list99.add(1);
list99.add(2);
list99.add(3);
List<Integer> list5 = new ArrayList<>();
list5.add(11);
list5.add(21);
list5.add(31);
List<Integer> list88 = new ArrayList<>();
list88.add(88);
list88.add(99);
list5.stream().map(t -> list99.add(t)).collect(Collectors.toList());
System.out.println(list99);
System.out.println("list................");
list88.stream().map(t -> list99.add(t)).collect(Collectors.toList());
System.out.println(list99);
// Stream<String> stringStream = Stream.of("e", "d", "c", "a", "f", "b");
// String st = stringStream.reduce("", (str1, str2) -> str1 = str1 + str2);
// System.out.println(st);*/
}
}