目录
6.1.5 find操作--findFirst和findAny
6.1.6 match 匹配操作--allMatch anyMatch
一、Lambda表达式
概念:Lambda表达式:特殊的匿名内部类,语法更简洁
Lambda表达式允许把函数作为一个方法的参数(函数作为方法参数传递),将代码像数据一样传递
匿名内部类:无需创建接口的实现类,可以之间创建接口对象
Runnable runnable=new Runnable() {
@Override
public void run() {
}
};
调用方法时:传递的参数可以是 基本类型,引用类型
语法:
函数式接口: 接口有只有一个抽象方法。这种接口就是函数式接口。
我们要想使用lambda表示,它的接口必须为函数式接口。
箭头左边:抽象方法的参数
->: 运算符
箭头右边: 抽象方法的方法体。
1.1 匿名内部类的冗余
public class Test {
public static void main(String[] args) {
//构造函数需要传递一个Runnable target类型的参数。而Runnable它是一个接口。
MyRunnable my=new MyRunnable();
Thread t=new Thread(my);
t.start();
//使用匿名内部类
Runnable runnable=new Runnable() {
@Override
public void run() {
System.out.println("~~~~~~~~~~~~~~这是匿名内部类");
}
};
Thread t2=new Thread(runnable);
t2.start();
}
}
class MyRunnable implements Runnable{
@Override
public void run() {
System.out.println("~~~~~~~~~~~~~~这是自定义接口实现类");
}
}
分析代码:
Thread 类需要 Runnable 接口作为参数,其中的抽象 run 方法是用来指定线程任务内容的核心
为了指定 run 的方法体,不得不需要 Runnable 接口的实现类
为了省去定义一个 Runnable 实现类的麻烦,不得不使用匿名内部类
必须覆盖重写抽象 run 方法,所以方法名称、方法参数、方法返回值不得不再写一遍,且不能写错
而实际上,似乎只有方法体才是关键所在。
我们就可以使用Lambda表达式
//lambda表达式 没有关注方法的名称 以及方法的返回类型 --lambda表示不会生成字节码文件
Runnable r=()->{
System.out.println("这是lambda表达式");
};
Thread t3=new Thread(r);
t3.start();
1.2 自定义无参无返回值的函数式接口
public class Test {
public static void main(String[] args) {
Swimming s=new Swimming() {
@Override
public void swiming() {
System.out.println("~~~~~~~~~~~~匿名内部类");
}
};
fun(s);
Swimming s2=()->{
System.out.println("lambda表达式============");
};
fun(s2);
}
//定义一个方法---传递的参数为接口类型---函数式接口
public static void fun(Swimming s){
s.swiming();
}
}
//它就是函数式接口
@FunctionalInterface
interface Swimming{
public void swiming();
}
1.3 自定义有参有返回值的函数式接口
public class Test02 {
public static void main(String[] args) {
//无需参数类型
Operator o = (arr) -> {
int sum = 0;
for (int b : arr) {
sum += b;
}
return sum;
};
fun(o);
}
public static void fun(Operator operator) {
int sum[] = {11, 12, 13, 14};
int sum1 = operator.getSum(sum);
System.out.println("数组中元素的和:" + sum1);
}
}
interface Operator {
//求数组中元素的和
public int getSum(int[] arr);
}
下面举例演示 java.util.Comparator 接口的使用场景代码,其中的抽象方法定义为:
public abstract int compare(T o1, T o2);
当需要对一个对象集合进行排序时, Collections.sort 方法需要一个 Comparator 接口实例来指定排序的规则。
public class Test03 {
public static void main(String[] args) {
List<Student> list=new ArrayList<>();
list.add(new Student("柳昌江",16));
list.add(new Student("汪豪杰",17));
list.add(new Student("闫克起",15));
list.add(new Student("刘洺宇",16));
//List<T> list,要排序的集合
// Comparator<? super T> c: 指明排序的规则
// Comparator<Student> comparator=new Comparator<Student>() {
// //返回0 表示o1和o2 相同 返回大于0
// @Override
// public int compare(Student o1, Student o2) {
// return o1.getAge()-o2.getAge();
// }
// };
Comparator<Student> comparator=(o1,o2)->{return o2.getAge()-o1.getAge();};
Collections.sort(list,comparator);
System.out.println(list);
}
}
class Student{
private String name;
private Integer age;
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", 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;
}
public Student(String name, Integer age) {
this.name = name;
this.age = age;
}
}
1.4 详细介绍Lambda表达式
什么时候使用lambda表达式?
调用某个方法时,该方法需要传递一个函数式接口参数时
二、函数式接口
概念: 如果一个接口只有一个抽象方法,则该接口称之为函数式接口,函数式接口可以使用Lambda表达式,Lambda表达式会被匹配到这个抽象方法上。
@FunctionalInterface 注解检测接口是否符合函数式接口
内置函数式接口的由来
public class Test {
public static void main(String[] args) {
Operator o=arr -> arr.length;
fun(o);
}
public static void fun(Operator operator) {
int sum[] = {11, 12, 13, 14};
int sum1 = operator.getSum(sum);
System.out.println("数组中元素的个数:" + sum1);
}
}
interface Operator {
//求数组中元素的和
public int getSum(int[] arr);
}
分析
我们知道使用Lambda表达式的前提是需要有函数式接口。而Lambda使用时不关心接口名,抽象方法名,只关心抽 象方法的参数列表和返回值类型。因此为了让我们使用Lambda方便,JDK提供了大量常用的函数式接口。 ---无需自定义函数式接口。---如果JDK不提供一些函数式接口,那么每个人需要自定义函数式接口,而且每个人定义的名称不一致。
内置的函数式接口都在 java.util.function包下
2.1 Consumer<T> 消费性函数式接口
T: 参数的泛型
void accept(T t);
方法中有参,无返回值。
/**
* Created by Intellij IDEA
*
* @author 王俊凯
* @Date: 2022/11/3 12:11
* @Version 1.0
*/
package com.wjk.demo05;
import java.util.function.Consumer;
/**
* 消费性函数式接口
* 有参无返回值
* 如果需要一个有参返回值的函数式接口,那么我们就可以使用Consumer函数式即可,无需自定义函数式接口
*/
public class Test05 {
public static void main(String[] args) {
Consumer<Double> consumer=a -> {
System.out.println("吃烧烤需要花:"+a);
};
fun(consumer,9999.99);
}
public static void fun(Consumer<Double> consumer,Double money){
consumer.accept(money);
}
}
2.2 Supplier<T> 供给型函数式接口
T:表示方法的返回值泛型 T get();
方法没有参数,有返回值。 当我们需要无参有返回值的函数式接口,就可以使用这种内置
/**
* Created by Intellij IDEA
*
* @author 王俊凯
* @Date: 2022/11/3 12:15
* @Version 1.0
*/
package com.wjk.demo06;
import java.util.function.Supplier;
/**
* T:表示方法的返回值泛型
* 方法没有参数,有返回值 当我们需要无参有返回值的函数式接口时,就可以用这种内置
* fun是自己写的方法,未来可能调用jdk自带的方法,参数也可能就是上面给的函数式接口。
*/
public class Test06 {
public static void main(String[] args) {
Supplier<String> s=()->{
return "八嘎";
};
fun(s);
}
public static void fun(Supplier<String> supplier){
String s = supplier.get();
System.out.println(s);
}
}
3.3 Funcation<T,R> 函数型函数式接口
T:参数的泛型
R: 返回值的泛型
R apply(T t);
这种函数式接口需要参数和有返回值。
/**
* Created by Intellij IDEA
*
* @author 王俊凯
* @Date: 2022/11/3 12:18
* @Version 1.0
*/
package com.wjk.demo07;
import java.util.function.Function;
/**
* Funcation<T,R> 函数型函数式接口
* T:参数的泛型
* R: 返回值的泛型
* R apply(T t);
* 这种函数式接口需要参数和有返回值
*/
public class Test07 {
public static void main(String[] args) {
Function<String,Integer> function=t->t.length();
fun(function,"hahahahahahahhahahahahahahahhaha");
}
public static void fun(Function<String,Integer> f,String str){
Integer apply = f.apply(str);
System.out.println(apply);
}
}
3.4 Predicate<T> 断言型函数式接口
boolean test(T t);
泛型: 参数的类型
返回值: boolean
根据参数做相应的条件判断,如果满足条件则返回true,不满足则返回false.
/**
* Created by Intellij IDEA
*
* @author 王俊凯
* @Date: 2022/11/4 9:11
* @Version 1.0
*/
package com.wjk.demo1104.demo01;
import java.util.function.BiPredicate;
import java.util.function.Predicate;
/**
* 断言型函数式接口
*/
public class TestPredicate {
public static void main(String[] args) {
//根据你传递的字符串,判断字符串的长度是否大于5
Predicate<String> p=t->{
return t.length()>5;
};
boolean baga = p.test("hello baga");
System.out.println(baga);
//boolean test (T t,U u)
BiPredicate<String,String> biPredicate=(t,u)->{
return t.equals(u);
};
boolean test = biPredicate.test("baga", "guizi");
System.out.println(test);
}
}
四、方法引用的使用场景
我们用Lambda表达式来实现匿名方法。但有些情况下,我们用Lambda表达式仅仅是调用一些已经存在的方法,除了调用方法外,没有其他任何多余的动作,在这种情况下,我们倾向于通过方法名来调用它,而Lambda表达式可以帮助我们实现这一要求,它使得Lambda在调用那些已经拥有方法名的方法的代码更简洁、更容易理解。方法引用可以理解为Lambda表达式的另外一种表现形式。方法引用要比lambda表达式语法更加简洁
方法引用: 理解为Lambda表达式的另一种表现。它的语法更加简洁。
方法引用使用的前提: lambda表达式中调用的是已经存在的方法,除了调用方法外,不能有任何其他操作,才可以使用方法引用。
4.1 方法引用的分类
类型 | 语法 | 对应的LAMBDA表达式 |
---|---|---|
静态方法引用 | 类名::staticMethod | (args) -> 类名.staticMethod(args) |
实例方法引用 | inst::instMethod | (args) -> inst.instMethod(args) |
对象方法引用 | 类名::instMethod | (inst,args) -> inst.instMethod(args) |
构建方法引用 | 类名::new | (args) -> new 类名(args) |
:: 是方法引用的符号。
4.2 方法引用的举例
静态方法的引用:当lambda表达式中,通过类名引用了一个已经存在的静态方法时。而且仅有一条语句
public class Test01 {
public static void main(String[] args) {
//void accept(T t);
//Consumer<int[]> consumer=(arr)->{Test01.sum(arr);};
//观察: 我们发现lambda表达式中有且仅有一条一句,而且这条语句,是调用了已经存在的方法。
Consumer<int[]> consumer=Test01::sum;
int[] arr={1,2,3,4};
consumer.accept(arr);
}
public static void sum(int[] arr) {
int sum = 0;
for (int a : arr) {
sum += a;
}
System.out.println("数组中元素的和:"+sum);
}
}
public class Test02 {
public static void main(String[] args) {
List<Integer> list=new ArrayList<>();
list.add(2);
list.add(3);
list.add(8);
list.add(4);
list.add(1);
//Comparator<Integer> comparator=(o1,o2)->Integer.compare(o1,o2);
Comparator<Integer> comparator=Integer::compare;
Collections.sort(list,comparator);
System.out.println(list);
}
}
实例方法的引用:实例方法引用 inst::instMethod (args) -> inst.instMethod(args)
/**
* Created by Intellij IDEA
*
* @author 王俊凯
* @Date: 2022/11/4 10:16
* @Version 1.0
*/
package com.wjk.demo1104.demo03;
import java.util.function.Supplier;
/**
* 实例方法引用
*/
public class Test03 {
public static void main(String[] args) {
//无参 有返回值
Teacher teacher=new Teacher("闫克起","35");
//Supplier<String> supplier=()-> teacher.getName();
//方法引用
Supplier<String> supplier=teacher::getName;
Supplier<String> supplier1=teacher::getAge;
System.out.println(supplier.get()+"********"+supplier1.get());
}
}
class Teacher{
private String name;
private String age;
@Override
public String toString() {
return "Teacher{" +
"name='" + name + '\'' +
", age='" + age + '\'' +
'}';
}
public Teacher(String name, String age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAge() {
return age;
}
public void setAge(String age) {
this.age = age;
}
}
对象方法引用 类名::instMethod (inst,args) -> inst.instMethod(args)
当lambda表达式第一个参数调用方法,而后面的参数作为方法的参数时。 我们可以考虑使用对象方法引用。
/**
* Created by Intellij IDEA
*
* @author 王俊凯
* @Date: 2022/11/4 10:19
* @Version 1.0
*/
package com.wjk.demo1104.demo04;
import java.util.function.BiPredicate;
/**
* 对象方法引用
*/
public class Test {
public static void main(String[] args) {
//比较两个字符串是否一致 断言式函数式接口
// BiPredicate<String,String> biPredicate=(o1,o2)->{
// return o1.equals(o2);
// };
//对象方法引用
BiPredicate<String,String> biPredicate=String::equals;
boolean test = biPredicate.test("八嘎", "baag");
System.out.println(test);
}
}
构建方法引用 类名::new (args) -> new 类名(args)
lambda表达式中只有一条语句,而且这条数据是实例一个对象,调用构造方法,而且构造函数的参数和lambda表达式的参数一致。
/**
* Created by Intellij IDEA
*
* @author 王俊凯
* @Date: 2022/11/4 10:23
* @Version 1.0
*/
package com.wjk.demo1104.demo05;
import java.util.function.Function;
import java.util.function.Supplier;
/**
* 构造方法引用
*/
public class Test {
public static void main(String[] args) {
//Function<String,Teacher> function=(t)->new Teacher(t);
//构造方法引用
Function<String,Teacher> function=Teacher::new;
Teacher apply = function.apply("闫克起");
System.out.println(apply);
}
}
class Teacher{
private String name;
public Teacher() {
}
@Override
public String toString() {
return "Teacher{" +
"name='" + name + '\'' +
'}';
}
public Teacher(String name) {
this.name = name;
}
}
五、Stream流
Java8的两个重大改变,一个是Lambda表达式,另一个就是本节要讲的Stream API表达式。Stream 是Java8中处理集合的关键抽象概念,它可以对集合进行非常复杂的查找、过滤、筛选等操作.
这种操作速度,要比操作数据库更快。 引用它基于JVM内存.
5.1 为什么要用Stream流
当我们需要对集合中的元素进行操作的时候,除了必需的添加、删除、获取外,最典型的就是集合遍历。我们来体验 集合操作数据的弊端,需求如下:
一个ArrayList集合中存储有以下数据:张无忌,周芷若,赵敏,张强,张三丰
需求:1.拿到所有姓张的 2.拿到名字长度为3个字的 3.打印这些数据
代码如下:
public class Test {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
Collections.addAll(list, "张无忌", "周芷若", "赵敏", "张强", "张三丰");
//1.获取所有姓张。
ArrayList<String> newList = new ArrayList<>();
for(String n:list){
if(n.startsWith("张")){
newList.add(n);
}
}
//2. 名字中含有三个的字
ArrayList<String> newList2 = new ArrayList<>();
for(String n:newList){
if(n.length()==3){
newList2.add(n);
}
}
//3.打印
for (String s:newList2){
System.out.println(s);
}
}
}
不过循环遍历有个弊端 这段代码中含有三个循环,每一个作用不同:
首先筛选所有姓张的人;
然后筛选名字有三个字的人;
最后进行对结果进行打印输出。
每当我们需要对集合中的元素进行操作的时候,总是需要进行循环、循环、再循环。这是理所当然的么?不是。循环 是做事情的方式,而不是目的。每个需求都要循环一次,还要搞一个新集合来装数据,如果希望再次遍历,只能再使 用另一个循环从头开始。
那Stream能给我们带来怎样更加优雅的写法呢?
使用Stream流来体验上面对集合的操作。
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
Collections.addAll(list, "张无忌", "周芷若", "赵敏", "张强", "张三丰");
// Consumer<String> consumer=item-> System.out.println(item);
list.stream()
.filter(item->item.startsWith("张"))
.filter(item->item.length()==3)
.forEach(item-> System.out.println(item));
}
5.2 Stream流式思想概述
Stream流式思想类似于工厂车间的“生产流水线”,Stream流不是一种数据结构,不保存数据,而是对数据进行加工 处理。Stream可以看作是流水线上的一个工序。在流水线上,通过多个工序让一个原材料加工成一个商品。
5.2.1 获取Stream流对象
这里获取流对象的方式有三种: 1. 通过集合名获取。 2. 通过Arrays中的静态方法获取streams 3. 通过Stream中的静态方法of
拿到流对象后才能操作Stream类中相关的方法
public class Test02 {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
Collections.addAll(list, "张无忌", "周芷若", "赵敏", "张强", "张三丰");
//通过集合对象调用stream方法获取
Stream<String> stream = list.stream();
//通过Arrays数组工具类调用stream方法。
String [] arr={"张三","李四","王五"};
Stream<String> stream1 = Arrays.stream(arr);
//通过Stream类中的方法获取Stream流对象
Stream<String> stream2 = Stream.of("张三", "李四", "王五");
}
}
5.2.2 中间操作的方法有哪些
一个操作的中间链,对数据源的数据进行操作。
举个简单的例子:
假设有一个Person类和一个Person列表,现在有两个需求:1)找到年龄大于18岁的人并输出;2)找出所有中国人的数量。
/**
* Created by Intellij IDEA
*
* @author 王俊凯
* @Date: 2022/11/4 14:27
* @Version 1.0
*/
package com.wjk.demo1104.demo07;
import java.util.ArrayList;
import java.util.List;
public class Test02 {
public static void main(String[] args) {
List<Person> personList = new ArrayList<>();
personList.add(new Person("欧阳雪",18,"中国",'F'));
personList.add(new Person("Tom",24,"美国",'M'));
personList.add(new Person("Harley",22,"英国",'F'));
personList.add(new Person("向天笑",20,"中国",'M'));
personList.add(new Person("李康",22,"中国",'M'));
personList.add(new Person("小梅",20,"中国",'F'));
personList.add(new Person("何雪",21,"中国",'F'));
personList.add(new Person("李康",22,"中国",'M'));
//找出年龄大于18
personList.stream().filter(item->{
return item.getAge()>18;
}).forEach(System.out::println);
System.out.println("*****************************");
//找出所有中国人
personList.stream().filter(item->item.getCountry().equals("中国")).forEach(System.out::println);
}
}
class Person {
private String name;
private Integer age;
private String country;
private char sex;
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
", country='" + country + '\'' +
", sex=" + sex +
'}';
}
public Person() {
}
public Person(String name, Integer age, String country, char sex) {
this.name = name;
this.age = age;
this.country = country;
this.sex = sex;
}
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;
}
public String getCountry() {
return country;
}
public void setCountry(String country) {
this.country = country;
}
public char getSex() {
return sex;
}
public void setSex(char sex) {
this.sex = sex;
}
}
六、讲解Stream流
6.1 Stream中的API
中间操作api: 一个操作的中间链,对数据源的数据进行操作。而这种操作的返回类型还是一个Stream对象。---中间操作如果没有调用终止操作的api,则中间操作的api不会被执行。
终止操作api: 一个终止操作,执行中间操作链,并产生结果,返回类型不在是Stream流对象。
6.1.1 filter 筛选操作
该方法需要一个断言型函数式接口参数,满足条件的留下,不满足条件的过滤掉。
public class Test03 {
public static void main(String[] args) {
List<Person> personList = new ArrayList<>();
personList.add(new Person("欧阳雪",18,"中国",'F'));
personList.add(new Person("Tom",24,"美国",'M'));
personList.add(new Person("Harley",22,"英国",'F'));
personList.add(new Person("向天笑",20,"中国",'M'));
personList.add(new Person("李康",22,"中国",'M'));
personList.add(new Person("小梅",20,"中国",'F'));
personList.add(new Person("何雪",21,"中国",'F'));
personList.add(new Person("李康",22,"中国",'M'));
//筛选出年龄大于20
// personList.stream().filter(item -> item.getAge() > 20).forEach(item-> System.out.println(item));
personList.stream().filter(item -> item.getAge() > 20).forEach(System.out::println);
}
}
class Person {
private String name;
private Integer age;
private String country;
private char sex;
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
", country='" + country + '\'' +
", sex=" + sex +
'}';
}
public Person() {
}
public Person(String name, Integer age, String country, char sex) {
this.name = name;
this.age = age;
this.country = country;
this.sex = sex;
}
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;
}
public String getCountry() {
return country;
}
public void setCountry(String country) {
this.country = country;
}
public char getSex() {
return sex;
}
public void setSex(char sex) {
this.sex = sex;
}
}
6.1.2 map 映射操作
map--接收Lambda,将元素转换成其他形式或提取信息。接收一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新的元素。
List<Person> personList = new ArrayList<>();
personList.add(new Person("欧阳雪",18,"中国",'F'));
personList.add(new Person("Tom",24,"美国",'M'));
personList.add(new Person("Harley",22,"英国",'F'));
personList.add(new Person("向天笑",20,"中国",'M'));
personList.add(new Person("李康",22,"中国",'M'));
personList.add(new Person("小梅",20,"中国",'F'));
personList.add(new Person("何雪",21,"中国",'F'));
personList.add(new Person("李康",22,"中国",'M'));
//map映射操作--名称
personList.stream().map(item->item.getName()).forEach(System.out::println);
6.1.3 sort排序操作
List<Person> personList = new ArrayList<>();
personList.add(new Person("欧阳雪",18,"中国",'F'));
personList.add(new Person("Tom",24,"美国",'M'));
personList.add(new Person("Harley",22,"英国",'F'));
personList.add(new Person("向天笑",20,"中国",'M'));
personList.add(new Person("李康",22,"中国",'M'));
personList.add(new Person("小梅",20,"中国",'F'));
personList.add(new Person("何雪",21,"中国",'F'));
personList.add(new Person("李康",22,"中国",'M'));
//sort排序操作--年龄
personList.stream().sorted((o1,o2)->Integer.compare(o1.getAge(),o2.getAge())).forEach(System.out::println);
6.1.4 提取和组合
流也可以进行合并、去重、限制、跳过等操作。 filter map sort concat distinct limit skip
public class Test04 {
public static void main(String[] args) {
String[] arr1 = { "a", "b", "c", "d" };
String[] arr2 = { "d", "e", "f", "g" };
Stream<String> stream1 = Stream.of(arr1);
Stream<String> stream2 = Stream.of(arr2);
//合并流
//Stream.concat(stream1,stream2).forEach(System.out::println);
//去重--distinct
// Stream.concat(stream1,stream2).distinct().forEach(System.out::println);
//获取前n个元素--limit
//Stream.concat(stream1,stream2).limit(5).forEach(System.out::println);
//跳过前n个元素
Stream.concat(stream1,stream2).skip(2).forEach(System.out::println);
}
}
6.1.5 find操作--findFirst和findAny
List<Person> personList = new ArrayList<>();
personList.add(new Person("Tom",24,"美国",'M'));
personList.add(new Person("欧阳雪",18,"中国",'F'));
personList.add(new Person("Harley",22,"英国",'F'));
personList.add(new Person("小梅",20,"中国",'F'));
personList.add(new Person("向天笑",20,"中国",'M'));
personList.add(new Person("李康",22,"中国",'M'));
personList.add(new Person("何雪",21,"中国",'F'));
personList.add(new Person("李康",22,"中国",'M'));
//find操作-- findFirst 获取流中第一个元素
// Optional<Person> first = personList.stream().findFirst();
// System.out.println(first.get());
//find操作---findAny() 获取流中任意一个元素 必须使用并行流测试
Optional<Person> any = personList.parallelStream().findAny();
System.out.println(any.get());
6.1.6 match 匹配操作--allMatch anyMatch
List<Person> personList = new ArrayList<>();
personList.add(new Person("Tom",24,"美国",'M'));
personList.add(new Person("欧阳雪",18,"中国",'F'));
personList.add(new Person("Harley",22,"英国",'F'));
personList.add(new Person("小梅",20,"中国",'F'));
personList.add(new Person("向天笑",20,"中国",'M'));
personList.add(new Person("李康",22,"中国",'M'));
personList.add(new Person("何雪",21,"中国",'F'));
personList.add(new Person("李康",22,"中国",'M'));
//匹配操作--所有元素都必须匹配条件 才返回true
// boolean b = personList.stream().allMatch(item -> item.getAge() > 10);
// System.out.println(b);
boolean b = personList.stream().anyMatch(item -> item.getAge() > 50);
System.out.println(b);
6.1.7 聚合操作 max min count
List<Person> personList = new ArrayList<>();
personList.add(new Person("Tom",24,"美国",'M'));
personList.add(new Person("欧阳雪",18,"中国",'F'));
personList.add(new Person("Harley",22,"英国",'F'));
personList.add(new Person("小梅",20,"中国",'F'));
personList.add(new Person("向天笑",20,"中国",'M'));
personList.add(new Person("李康",22,"中国",'M'));
personList.add(new Person("何雪",21,"中国",'F'));
personList.add(new Person("李康",22,"中国",'M'));
//聚合操作---count
// long count = personList.stream().count();
// System.out.println("个数:"+count);
//聚合操作---max min
Optional<Person> max = personList.stream().max((o1, o2) -> o1.getAge() - o2.getAge());
System.out.println(max.get());
6.1.8 reduce规约操作
public class Test05 {
public static void main(String[] args) {
Integer [] arr={2,3,4,5,6,2};
//第一次赋值时,会把集合中的前两个元素赋值于t1 t2 后面会把方法计算的结果赋予t1 在集合的后面的元素赋予t2
Optional<Integer> reduce = Arrays.stream(arr).reduce((t1, t2) -> t1+=t2);
System.out.println(reduce.get());
}
}
6.2 collect搜集操作
计数: count
平均值: averagingInt、 averagingLong、 averagingDouble
最值: maxBy、 minBy
求和: summingInt、 summingLong、 summingDouble
List<Person> personList = new ArrayList<>();
personList.add(new Person("Tom",24,"美国",'M'));
personList.add(new Person("欧阳雪",18,"中国",'F'));
personList.add(new Person("Harley",22,"英国",'F'));
personList.add(new Person("小梅",20,"中国",'F'));
personList.add(new Person("向天笑",20,"中国",'M'));
personList.add(new Person("李康",22,"中国",'M'));
personList.add(new Person("何雪",21,"中国",'F'));
personList.add(new Person("李康",22,"中国",'M'));
// Long collect =personList.stream().collect(Collectors.counting());
// System.out.println(collect);
// Double collect = personList.stream().collect(Collectors.averagingInt(item -> item.getAge()));
// System.out.println(collect);
// Optional<Person> collect = personList.stream().collect(Collectors.maxBy(((o1, o2) -> o1.getAge() - o2.getAge())));
// System.out.println(collect);
Integer collect = personList.stream().collect(Collectors.summingInt(item -> item.getAge()));
System.out.println(collect);
搜集为一个新的集合。
List<Person> personList = new ArrayList<>();
personList.add(new Person("Tom",24,"美国",'M'));
personList.add(new Person("欧阳雪",18,"中国",'F'));
personList.add(new Person("Harley",22,"英国",'F'));
personList.add(new Person("小梅",20,"中国",'F'));
personList.add(new Person("向天笑",20,"中国",'M'));
personList.add(new Person("李康",22,"中国",'M'));
personList.add(new Person("何雪",21,"中国",'F'));
// Set<String> set = personList.stream().filter(item -> item.getAge() > 20)
// .filter(item -> item.getCountry().equals("中国"))
// .map(item -> item.getName())
// .collect(Collectors.toSet());
// System.out.println(set);
Map<String, Person> map = personList.stream().filter(item -> item.getAge() > 20)
.filter(item -> item.getCountry().equals("中国"))
.collect(Collectors.toMap(item -> item.getName(), item -> item));
System.out.println(map);
分组操作
List<Person> personList = new ArrayList<>();
personList.add(new Person("Tom",24,"美国",'M'));
personList.add(new Person("欧阳雪",18,"中国",'F'));
personList.add(new Person("Harley",22,"英国",'F'));
personList.add(new Person("小梅",20,"中国",'F'));
personList.add(new Person("向天笑",20,"中国",'M'));
personList.add(new Person("李康",22,"中国",'M'));
personList.add(new Person("何雪",21,"中国",'F'));
Map<Character, List<Person>> collect = personList.stream().collect(Collectors.groupingBy(item -> item.getSex()));
System.out.println(collect);
七、JDK8中日期时间类
public class Test {
public static void main(String[] args) {
// //自定义时间的日期---设计不合理。
// Date date=new Date(2022,11,5);
// System.out.println(date);
//
// //时间格式转化---存在线程安全问题
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
// System.out.println(sdf.format(date));
for (int i = 0; i <10 ; i++) {
new Thread(new Runnable() {
@Override
public void run() {
try {
System.out.println(sdf.parse("2022-11-05"));
} catch (ParseException e) {
e.printStackTrace();
}
}
}).start();
}
}
}
日期时间类设计不合理---两个包下都有Date. Date的年需要从1900算起。
日期转化类存在线程安全问题。
jdk8后提供了新的日期时间类以及转化类。java.time包下
7.1 日期时间
public class Test {
public static void main(String[] args) {
//创建一个指定日期时间的类
LocalDateTime dateTime = LocalDateTime.of(2022, 10, 11, 17, 18, 16);
//创建当前的日期时间对象
LocalDateTime now = LocalDateTime.now();
System.out.println("指定的日期时间:"+dateTime.toString());
System.out.println("当前的日期时间:"+now);
}
private static void getTime(){
//获取一个指定的时间
LocalTime time = LocalTime.of(11, 11, 11);
//获取当前的时间
LocalTime now = LocalTime.now();
System.out.println("指定的时间:"+time);
System.out.println("当前的时间:"+now);
//时间类中常用的方法
System.out.println("获取时间的小时:"+now.getHour());
System.out.println("获取时间的分钟:"+now.getMinute());
System.out.println("获取时间的秒:"+now.getSecond());
System.out.println("获取时间的纳秒:"+now.getNano());
}
private static void getDate(){
//创建一个LocalDate日期类。--创建指定的日期
LocalDate date = LocalDate.of(2022, 10, 7);
//创建一个当前日期
LocalDate now = LocalDate.now();
System.out.println("指定的日期:"+date);
System.out.println("当前日期:"+now);
//日期类中的常见的方法
System.out.println("获取日期的年份:"+now.getYear());
System.out.println("获取日期的月份:"+now.getMonth().getValue());
System.out.println("获取日期的星期:"+now.getDayOfWeek().getValue());
}
}
7.2 把日期时间转化为字符串和字符串解析为日期时间
DateTimeFormate 可以进行日期时间和字符串的转化
(1) 把日期时间转化为指定格式的字符串。
public static void main(String[] args) {
LocalDateTime now = LocalDateTime.now();
System.out.println("转化前的日期时间:"+now);
DateTimeFormatter dtf=DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss");
String format = now.format(dtf);
System.out.println("转化后:"+format);
}
(2)把字符串转化为日期时间对象
public static void main(String[] args) {
DateTimeFormatter dtf=DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss");
LocalDateTime dateTime = LocalDateTime.parse("2020/11/17 22:22:22", dtf);
System.out.println(dateTime);
}
7.3 日期时间比较类.
public class Test {
public static void main(String[] args) {
LocalDate date = LocalDate.of(2020, 11, 1);
LocalDate now = LocalDate.now();
//比较两个日期的距离
Period period = Period.between(date, now);
System.out.println("相差的年:"+ period.getYears());
System.out.println("相差的月:"+ period.getMonths());
System.out.println("相差的天:"+ period.getDays());
LocalTime time = LocalTime.of(8, 12, 12);
LocalTime now1 = LocalTime.now();
Duration between = Duration.between(time, now1);
System.out.println(between.toHours());
System.out.println(between.toMinutes()); //时间与时间之间相差的分钟
System.out.println(between.getSeconds());//时间与时间之间相差的秒
}
}