18.1 lambda 表达式
Lambda 表达式 − Lambda 允许把函数作为一个方法的参数(函数作为参数传递到方法中)。
new Thread(()->{
System.out.println("helloworld");
}).start(); //定义一个线程并启动,线程任务是打印hellworld.
分开写:
Runnable target=()->{System.out.println("helloworld");};
new Thread(target).start();
Lambda表达式 ->为界分为左右两边,左边映射的是方法的参数,右边映射的是方法的方法体,通用Lambda表达式描述的一定是一个函数式接口 所谓函数式接口 @FunctionInterface 注解 , 这个接口中只能有一个方法的定义,static default方法不算
写法:
1、完整写法 (参数列表)->{操作代码} 参数列表多个之间使用逗号分隔,参数列表的名称可以和方法中的参数不一样,按位置一一对应。
2、如果没有参数或者多个参数
没有参数 : () -> { 操作代码 }
多个参数: (c1,c2,c3)->{ 操作代码 }
3、如果只有一个参数 (c)->{} 简写:只有一个参数可以取消小括号 c->{操作代码}
4、如果执行体有多句代码,大括号不能省略 ()->{代码.......};
5、如果执行体只有一句代码,可以省略大括号 ()->System.out.println("...");
6、如果只有一个参数,执行体只有一句代码 (x)-> {System.out.println(x);} 简写 x-> System.out.println(x);
7、如果执行体只有一句代码且该代码是返回代码可以省略大括号和return ()-> {return 1 2 3; } 简写 ()->1 2 3;
18.2 四大基本函数式接口
1、Interface Consumer<T> 消费型接口
void accept(T t); 在Consumer中有一个带一个参数没有返回值的方法定义,Java8认为你以后遇上这类需求时,可以不用再去定义多余的接口了,直接使用系统提供的这个。
消费型接口,好似封装的set方法 setName(String name)
代码语言:javascript复制import java.util.function.Consumer;
public class ConsumerDemo {
public static void main(String[] args) {
//lambda表达式就是在以匿名内部类的方式实现当前这个接口里面的方法,如果你不调用这个方法,一辈子都不会执行
Consumer<String> consumer=s -> {
System.out.println(s);
};
consumer.accept("你好");
}
}
2、Interface Supplier<T> 供给型接口
T get() 认为不带参数但是有一个返回值的这种需求就使用这个供给型接口。 好似封装的get方式,getName()
代码语言:javascript复制package com.qf.function;
import java.util.function.Supplier;
public class SupplierDemo {
public static void main(String[] args) {
Supplier<String> supplier=()->"helloworld";
System.out.println(supplier.get());
}
}
3、Interface Function<T,R> 函数接口 T target参数 R return返回值
R apply(T t); 有一个参数带一个返回值的这种需求。
代码语言:javascript复制public class SupplierDemo {
public static void main(String[] args) {
Function<Integer,Double> fun=(r)->{
double result=r*r*3.1415926;
return result;
};
System.out.println(fun.apply(5));
}
}
4、 Interface Predicate<T> 断言型接口
boolean test(T t); 有一个参数,然后返回一个布尔值,这就是断言型接口
代码语言:javascript复制public class SupplierDemo {
public static void main(String[] args) {
Predicate<Integer> pre=t->t<0;
System.out.println(pre.test(10));
}
}
18.3 forEach迭代
java 8--> JDK1.8版本 forEach 真正的forEach ,
for(String str : list){ } 我在讲课的时候我也叫这个for循环为foreach,采取的是迭代的形式
forEach源码:方法结构:
代码语言:javascript复制default void forEach(Consumer<? super T> action){}
代码语言:javascript复制default void forEach(Consumer<? super T> action) {
//判断当前的Consumer对象是否为空
Objects.requireNonNull(action);
//this是一个ArrayList集合
// List<Integer> list= Arrays.asList(12,321,12,4543,34,54,2,2,2334,23);
//t 经历 12,321,12,4543.......
for (T t : this) {
//使用传递过来的Consumer对象将迭代数据传递到accept方法中去进行操作
//具体是什么操作
action.accept(t);
}
}
代码语言:javascript复制public class Demo1 {
public static void main(String[] args) {
List<Integer> list= Arrays.asList(12,321,12,4543,34,54,2,2,2334,23);
//第一种 action.accept(t);具体的操作要看这里具体的实现
Consumer<Integer> consumer= s -> {
System.out.println(s);
};
list.forEach(consumer);
}
}
代码语言:javascript复制public class Demo1 {
public static void main(String[] args) {
List<Integer> list= Arrays.asList(12,321,12,4543,34,54,2,2,2334,23);
//第一种
Consumer<Integer> consumer= s -> {
System.out.println(s);
};
list.forEach(consumer);
//第二种
list.forEach(s -> {
System.out.println("hello");
System.out.println(s);
System.out.println("====================");
});
}
}
结论,第一种和第二种是同一本质
18.4 方法的引用
方法引用通过方法的名字来指向一个方法。
方法引用可以使语言的构造更紧凑简洁,减少冗余代码。
方法引用使用一对冒号 :: 。
方法如果你手中已经有了一个实现过的方法,这个方法的特征与四大基础性函数接口一致时可以直接使用该方法的引用来实现
代码语言:javascript复制public class Demo1 {
public static void main(String[] args) {
List<Integer> list= Arrays.asList(12,321,12,4543,34,54,2,2,2334,23);
//第三种 是方法的引用
list.forEach(System.out::println);
System.out.println();
}
}
第一种:静态方法的引用
类名::方法名
代码语言:javascript复制public class Demo1 {
public static void main(String[] args) {
List<Integer> list= Arrays.asList(12,321,12,4543,34,54,2,2,2334,23);
list.forEach(Demo1::show);//静态方法的引用,将该方法使用Consumer对象的实现传递进去由action来调用
}
public static void show(Integer n){
FileOutputStream fdOut = new FileOutputStream(FileDescriptor.out);
PrintStream out=new PrintStream(fdOut);
out.println(n);
}
}
第二种:特定对象的方法引用
代码语言:javascript复制public class Demo1 {
public static void main(String[] args) {
List<Integer> list= Arrays.asList(12,321,12,4543,34,54,2,2,2334,23);
//创建对象
Demo1 demo=new Demo1();
//对象::方法
list.forEach(demo::show);
}
//非静态方法
public void show(Integer n){
FileOutputStream fdOut = new FileOutputStream(FileDescriptor.out);
PrintStream out=new PrintStream(fdOut);
out.println(n);
}
}
第三种: 构造器引用
代码语言:javascript复制public class Demo1 {
public static void main(String[] args) {
List<Integer> list= Arrays.asList(12,321,12,4543,34,54,2,2,2334,23);
// 类名::new 这里会创建对象出来,只创建一个
list.forEach(Demo1::new);
}
//这是一个构造方法
public Demo1(Integer n){
FileOutputStream fdOut = new FileOutputStream(FileDescriptor.out);
PrintStream out=new PrintStream(fdOut);
out.println(n);
}
}
第四种:特定类的任意对象的方法引用 类名::方法名
代码语言:javascript复制public class Demo1 {
public static void main(String[] args) {
List<Integer> list= Arrays.asList(12,321,12,4543,34,54,2,2,2334,23);
list.forEach(Demo1::show); //需要有特定的环境,不然还是会报错 Stream流的时候
}
public void show(Integer n){
FileOutputStream fdOut = new FileOutputStream(FileDescriptor.out);
PrintStream out=new PrintStream(fdOut);
out.println(n);
}
}
代码语言:javascript复制public class Student {
private Integer stuNo;
private String stuName;
public Student(Integer stuNo, String stuName) {
this.stuNo = stuNo;
this.stuName = stuName;
}
public void show(){
System.out.println(this.getStuName());
}
}
代码语言:javascript复制public class Demo2 {
public static void main(String[] args) {
List<Student> list=new ArrayList<>();
list.add(new Student(1,"张鹏"));
list.add(new Student(2,"谢兴灵"));
list.add(new Student(3,"冯小龙"));
list.add(new Student(4,"蔡金恩"));
list.forEach(Student::show);
}
}
public void show(){ System.out.println(this.getStuName()); }中不能代参数因为
代码语言:javascript复制default void forEach(Consumer<? super T> action) {
Objects.requireNonNull(action);
for (T t : this) {
action.accept(t);//这里要去调用show方法 在内部中使用t在调用Show所有呢show方法this就是这个t
}
}
总结:
1、类任意方法的引用在Consumer接口或者BiConsumer接口中始终要留一个参数位置(第一个参数)来接收调用引用方法的对象。
2、特定类任意方法的引用一般情况下用于集合上,为什么是集合,因为集合中的元素是具体的对象
3、引用的方法必须是当前集合的类型这个类中定义的方法
代码语言:javascript复制//iterable接口中的 用是的Consumer accept 参一个参数
default void forEach(Consumer<? super T> action) {
Objects.requireNonNull(action);
for (T t : this) {
action.accept(t);
}
}
//这是自己写的 BiConsumer accept 参两个参数
public void forEach1(BiConsumer<E,Integer> action){
for (E t : this){
action.accept(t,1);
}
}
//始终要留有一个参数位来接收对象
代码语言:javascript复制public class Student{
//show方法的编写1
public void show(){
System.out.println(this);
}
//show方法的编写2
public void show(Integer i){
System.out.println(i);
System.out.println(this);
}
}
调用:
代码语言:javascript复制public class Demo2 {
public static void main(String[] args) {
MyList<Student> list=new MyList<>();
list.add(new Student(1,"张鹏"));
list.add(new Student(2,"谢兴灵"));
list.add(new Student(3,"冯小龙"));
list.add(new Student(4,"蔡金恩"));
list.forEach(Student::show); //调用的不带参数的show方法
list.forEach1(Student::show);//调用的带一个参数的show方法
}
}
18.5 lombok
代码语言:javascript复制<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.12</version>
</dependency>
</dependencies>
使用小辣椒要先对idea安装插件
重启idea
第一使用的时候在运行程序的时候可能会有问题,报错 找不到符号
lombok
@Data 添加get set 方法,重写toString,equals 等方法
@AllArgsConstructor 全参构造
@NoArgsConstructor 无参构造
@Accessors(chain = true) 启动链式编程
@Getter 只添加get方法
@Setter 只添加set方法
18.6 流式计算
Stream 它出现的目的就是让对集合数据的筛选,统计,查询和sql语句一样简单
语法:
list.stream()--> Stream(接口)对象,定义了所有的流式计算的规则,这些规则与上面讲的四大函数式接口息息相关。
统计重庆的女生有多少个
代码语言:javascript复制import java.util.ArrayList;
import java.util.List;
public class Demo3 {
public static void main(String[] args) {
List<Student> list=new ArrayList<>();
list.add(new Student().setStuNo(1).setStuName("张鹏").setSex("男").setPhone("13312345678").setAddress("重庆市沙坪坝区"));
list.add(new Student(2,"谢灵儿","女","13311111111","重庆市江北区观音桥"));
list.add(new Student(6,"冯小龙","男","1332222222","重庆市渝北区人和"));
list.add(new Student(4,"蔡金恩","女","1888888888","重庆市北碚区西南大学"));
list.add(new Student(25,"王浩月","女","1323333333","重庆市渝中区解放碑"));
list.add(new Student(19,"姜春阳","女","1555555555","黑龙江省哈尔滨市九龙坡区石桥铺"));
list.add(new Student(16,"陈朋","男","1777777777","重庆市南岸区南坪"));
list.add(new Student(88,"王政","男","1399999999","重庆市巴南区李家沱"));
list.add(new Student(39,"浩楠哥","男","16666666666","重庆市九龙区铜锣山"));
System.out.println(list.stream().filter(s -> s.getSex().equals("女") && s.getAddress().startsWith("重庆市")).count());
}
}
filter() 提供给我们写条件筛选数据的地方 select * from Student where gender='女' and no>=25
代码语言:javascript复制Stream<T> filter(Predicate<? super T> predicate);
内部是一个Pridicate断言函数式接口,代表者数据筛选返回true数据留下来,返回false筛选掉。filter执行完成之后并没有拿到最终的结果,返回的还是一个Stream流对象。
collect()方法收集
Collectors 收集器 toList()
collect(Collectors.toList())将stream中的数据以list的形式收集起来,返回一个list
代码语言:javascript复制List<Student> collect = list.stream().filter(s -> "女".equals(s.getSex())).collect(Collectors.toList());
使用filter对女生数据进行筛选,以list的形式将筛选后的数据收集起来,生成一个新的list
map() 用于指定要显示哪些属性信息 类似于 sql语句中select 后面对列名的指定 select id,name,gender,phone from Student;
代码语言:javascript复制<R> Stream<R> map(Function<? super T, ? extends R> mapper);
内部是一个Function接口,function接口定义的方法是一个参数一个返回值,返回值就是要显示的内容,参数是你的迭代对象。
第一种使用lambda表达式的形式
List<String> collect = list.stream().filter(s -> "女".equals(s.getSex())).map(s->s.getStuName()).collect(Collectors.toList());
第二种使用方法引用,类的任意方法引用
List<String> collect = list.stream().filter(s -> "女".equals(s.getSex())).map(Student::getStuName).collect(Collectors.toList());
代码语言:javascript复制package com.qf.lambdaDemo;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
public class Demo3 {
public static void main(String[] args) {
List<Student> list=new ArrayList<>();
list.add(new Student().setStuNo(1).setStuName("张鹏").setSex("男").setPhone("13312345678").setAddress("重庆市沙坪坝区"));
list.add(new Student(2,"谢灵儿","女","13311111111","重庆市江北区观音桥"));
list.add(new Student(6,"冯小龙","男","1332222222","重庆市渝北区人和"));
list.add(new Student(4,"蔡金恩","女","1888888888","重庆市北碚区西南大学"));
list.add(new Student(25,"王浩月","女","1323333333","重庆市渝中区解放碑"));
list.add(new Student(19,"姜春阳","女","1555555555","黑龙江省哈尔滨市九龙坡区石桥铺"));
list.add(new Student(16,"陈朋","男","1777777777","重庆市南岸区南坪"));
list.add(new Student(88,"王政","男","1399999999","重庆市巴南区李家沱"));
list.add(new Student(39,"浩楠哥","男","16666666666","重庆市九龙区铜锣山"));
//筛选出女生的信息返回一个list
// List<Student> collect = list.stream().filter(s -> "女".equals(s.getSex())).collect(Collectors.toList());
//筛选出女生的信息只显示某部分属性返回一个list
List<String> collect = list.stream().filter(s -> "女".equals(s.getSex())).map(Student::getStuName).collect(Collectors.toList());
System.out.println(collect);
}
}
结果:
[谢灵儿, 蔡金恩, 王浩月, 姜春阳]
这个做只能显示一个姓名,现在,要求显示学号,姓名,性别?
代码语言:javascript复制public class Demo3 {
public static void main(String[] args) {
List<Student> list=new ArrayList<>();
list.add(new Student().setStuNo(1).setStuName("张鹏").setSex("男").setPhone("13312345678").setAddress("重庆市沙坪坝区"));
list.add(new Student(2,"谢灵儿","女","13311111111","重庆市江北区观音桥"));
list.add(new Student(6,"冯小龙","男","1332222222","重庆市渝北区人和"));
list.add(new Student(4,"蔡金恩","女","1888888888","重庆市北碚区西南大学"));
list.add(new Student(25,"王浩月","女","1323333333","重庆市渝中区解放碑"));
list.add(new Student(19,"姜春阳","女","1555555555","黑龙江省哈尔滨市九龙坡区石桥铺"));
list.add(new Student(16,"陈朋","男","1777777777","重庆市南岸区南坪"));
list.add(new Student(88,"王政","男","1399999999","重庆市巴南区李家沱"));
list.add(new Student(39,"浩楠哥","男","16666666666","重庆市九龙区铜锣山"));
/*
* map中只能返回一个值,如果要返回多个信息的时候,这一个值一定要具体包含多条件信息的功能
* 数组 集合 map 新建一个类
*/
List<List<String>> collect = list.stream().filter(s -> "女".equals(s.getSex())).map(s -> {
List<String> stus = new ArrayList<>();
stus.add(s.getStuNo().toString());
stus.add(s.getStuName());
stus.add(s.getSex());
return stus;
}).collect(Collectors.toList());
System.out.println("学号tt姓名tt性别");
for (int i = 0; i < collect.size(); i ) {
List<String> stus=collect.get(i);
for (String s: stus) {
System.out.print(s "tt");
}
System.out.println();
}
}
}
新建一个类存放筛选过后的结果:
代码语言:javascript复制package com.qf.lambdaDemo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class ResultStudent {
private Integer stuNo;
private String stuName;
private String sex;
public ResultStudent(Student student) {
this.stuNo=student.getStuNo();
this.stuName=student.getStuName();
this.sex=student.getSex();
}
}
代码语言:javascript复制package com.qf.lambdaDemo;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
public class Demo3 {
public static void main(String[] args) {
List<Student> list=new ArrayList<>();
list.add(new Student().setStuNo(1).setStuName("张鹏").setSex("男").setPhone("13312345678").setAddress("重庆市沙坪坝区"));
list.add(new Student(2,"谢灵儿","女","13311111111","重庆市江北区观音桥"));
list.add(new Student(6,"冯小龙","男","1332222222","重庆市渝北区人和"));
list.add(new Student(4,"蔡金恩","女","1888888888","重庆市北碚区西南大学"));
list.add(new Student(25,"王浩月","女","1323333333","重庆市渝中区解放碑"));
list.add(new Student(19,"姜春阳","女","1555555555","黑龙江省哈尔滨市九龙坡区石桥铺"));
list.add(new Student(16,"陈朋","男","1777777777","重庆市南岸区南坪"));
list.add(new Student(88,"王政","男","1399999999","重庆市巴南区李家沱"));
list.add(new Student(39,"浩楠哥","男","16666666666","重庆市九龙区铜锣山"));
/*
map中这次使用的是方法的引用,调用的是ResultStudent中的构造方法,在调用构造方法的时候会把Student类型的迭代变量传递
进去,所以在ResultStudent类中写了个Student为参数的构造,也就是将student对象的值一个一个的给到ResultStudent对象中。map返回值的类型就变成了ResultStudent返回在收集器收集成集合的时候,返回的也是一个ResultStudent集合。
*/
List<ResultStudent> collect = list.stream().filter(s -> "女".equals(s.getSex())).map(ResultStudent::new).collect(Collectors.toList());
System.out.println(collect);
}
}
skip(数量) 表示要跳过几条记录
limit(数量) 表示要显示几条记录
这两个一组合可以做到分页的效果
代码语言:javascript复制import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
public class Demo3 {
public static void main(String[] args) {
List<Student> list=new ArrayList<>();
list.add(new Student().setStuNo(1).setStuName("张鹏").setSex("男").setPhone("13312345678").setAddress("重庆市沙坪坝区"));
list.add(new Student(2,"谢灵儿","女","13311111111","重庆市江北区观音桥"));
list.add(new Student(6,"冯小龙","男","1332222222","重庆市渝北区人和"));
list.add(new Student(4,"蔡金恩","女","1888888888","重庆市北碚区西南大学"));
list.add(new Student(25,"王浩月","女","1323333333","重庆市渝中区解放碑"));
list.add(new Student(19,"姜春阳","女","1555555555","黑龙江省哈尔滨市九龙坡区石桥铺"));
list.add(new Student(16,"陈朋","男","1777777777","重庆市南岸区南坪"));
list.add(new Student(88,"王政","男","1399999999","重庆市巴南区李家沱"));
list.add(new Student(39,"浩楠哥","男","16666666666","重庆市九龙区铜锣山"));
//筛选出女生的信息返回一个list
// List<Student> collect = list.stream().filter(s -> "女".equals(s.getSex())).collect(Collectors.toList());
//筛选出女生的信息只显示某部分属性返回一个list
System.out.println(list.stream().filter(s -> "女".equals(s.getSex())).map(ResultStudent::new).collect(Collectors.toList()));
System.out.println("========================================================================");
List<ResultStudent> collect = list.stream().filter(s ->
//跳筛选数据的前3条件记录,只显示留余数据的第一条记录
"女".equals(s.getSex())).map(ResultStudent::new).skip(3).limit(1).collect(Collectors.toList());
System.out.println(collect);
}
}
distinct() 去除数据源中的重复数据
代码语言:javascript复制public class Demo3 {
public static void main(String[] args) {
List<Student> list=new ArrayList<>();
list.add(new Student(1,"张鹏","男","13312345678","重庆市沙坪坝区"));
list.add(new Student(2,"谢灵儿","女","13311111111","重庆市江北区观音桥"));
list.add(new Student(6,"冯小龙","男","1332222222","重庆市渝北区人和"));
list.add(new Student(4,"蔡金恩","女","1888888888","重庆市北碚区西南大学"));
list.add(new Student(25,"王浩月","女","1323333333","重庆市渝中区解放碑"));
list.add(new Student(19,"姜春阳","女","1555555555","黑龙江省哈尔滨市九龙坡区石桥铺"));
list.add(new Student(16,"陈朋","男","1777777777","重庆市南岸区南坪"));
list.add(new Student(88,"王政","男","1399999999","重庆市巴南区李家沱"));
list.add(new Student(39,"浩楠哥","男","16666666666","重庆市九龙区铜锣山"));
list.add(new Student(39,"浩楠哥","男","16666666666","重庆市九龙区铜锣山"));
List<ResultStudent> collect = list.stream().map(ResultStudent::new).distinct().collect(Collectors.toList());
collect.forEach(System.out::println);
}
}
两个new出来的对象是去不了重的,原因是因为Object类的hashcode值不一样,两次new是生成了两个对象,他们的内存地址也不一样。
如果要对对象进行去重要重写equals方法因为Object中的equals直接判断是地址,重写以后会一个属性值一个属性的进行对比,这样才能去重
代码语言:javascript复制public class Student {
private Integer stuNo;
private String stuName;
private String sex;
private String phone;
private String address;
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Student student = (Student) o;
return Objects.equals(stuNo, student.stuNo) &&
Objects.equals(stuName, student.stuName) &&
Objects.equals(sex, student.sex) &&
Objects.equals(phone, student.phone) &&
Objects.equals(address, student.address);
}
@Override
public int hashCode() {
return Objects.hash(stuNo, stuName, sex, phone, address);
}
}
count() 统计数量,一般加上条件的统计才有意义,如果要统计数据源中所有的数量直接就list.size();
代码语言:javascript复制public class Demo3 {
public static void main(String[] args) {
List<Student> list=new ArrayList<>();
list.add(new Student(1,"张鹏","男","13312345678","重庆市沙坪坝区"));
list.add(new Student(2,"谢灵儿","女","13311111111","重庆市江北区观音桥"));
list.add(new Student(6,"冯小龙","男","1332222222","重庆市渝北区人和"));
list.add(new Student(4,"蔡金恩","女","1888888888","重庆市北碚区西南大学"));
list.add(new Student(25,"王浩月","女","1323333333","重庆市渝中区解放碑"));
list.add(new Student(19,"姜春阳","女","1555555555","黑龙江省哈尔滨市九龙坡区石桥铺"));
list.add(new Student(16,"陈朋","男","1777777777","重庆市南岸区南坪"));
list.add(new Student(88,"王政","男","1399999999","重庆市巴南区李家沱"));
list.add(new Student(39,"浩楠哥","男","16666666666","重庆市九龙区铜锣山"));
list.add(new Student(39,"浩楠哥111","女","16666666666","重庆市九龙区铜锣山"));
long count = list.stream().filter(s->s.getStuNo()>30).count();
}
}
max(),min()
代码语言:javascript复制Optional<T> max(Comparator<? super T> comparator);
Optional<T> min(Comparator<? super T> comparator);
Comparator接口的比较方法有两个参数,所以max和min在写lambda表达式的时候要入参两个参数
代码语言:javascript复制public class Demo3 {
public static void main(String[] args) {
List<Student> list=new ArrayList<>();
list.add(new Student(1,"张鹏","男","13312345678","重庆市沙坪坝区"));
list.add(new Student(2,"谢灵儿","女","13311111111","重庆市江北区观音桥"));
list.add(new Student(6,"冯小龙","男","1332222222","重庆市渝北区人和"));
list.add(new Student(4,"蔡金恩","女","1888888888","重庆市北碚区西南大学"));
list.add(new Student(25,"王浩月","女","1323333333","重庆市渝中区解放碑"));
list.add(new Student(19,"姜春阳","女","1555555555","黑龙江省哈尔滨市九龙坡区石桥铺"));
list.add(new Student(16,"陈朋","男","1777777777","重庆市南岸区南坪"));
list.add(new Student(88,"王政","男","1399999999","重庆市巴南区李家沱"));
list.add(new Student(39,"浩楠哥","男","16666666666","重庆市九龙区铜锣山"));
list.add(new Student(39,"浩楠哥111","女","16666666666","重庆市九龙区铜锣山"));
Optional<Student> max = list.stream().max((o1, o2) -> o1.getStuNo() - o2.getStuNo());
System.out.println(max.get());
Optional<Student> min = list.stream().min((o1, o2) -> o1.getStuNo() - o2.getStuNo());
System.out.println(min.get());
}
}
mapToInt()
mapToDouble()
返回一个聚合流来取结果
聚合函数 5个
求合
求平均值
求最大值
求最小值
统计个数
代码语言:javascript复制import java.util.*;
import java.util.stream.Collectors;
public class Demo3 {
public static void main(String[] args) {
List<Student> list=new ArrayList<>();
list.add(new Student(1,"张鹏","男","13312345678","重庆市沙坪坝区"));
list.add(new Student(2,"谢灵儿","女","13311111111","重庆市江北区观音桥"));
list.add(new Student(6,"冯小龙","男","1332222222","重庆市渝北区人和"));
list.add(new Student(4,"蔡金恩","女","1888888888","重庆市北碚区西南大学"));
list.add(new Student(25,"王浩月","女","1323333333","重庆市渝中区解放碑"));
list.add(new Student(19,"姜春阳","女","1555555555","黑龙江省哈尔滨市九龙坡区石桥铺"));
list.add(new Student(16,"陈朋","男","1777777777","重庆市南岸区南坪"));
list.add(new Student(88,"王政","男","1399999999","重庆市巴南区李家沱"));
list.add(new Student(39,"浩楠哥","男","16666666666","重庆市九龙区铜锣山"));
list.add(new Student(39,"浩楠哥111","女","16666666666","重庆市九龙区铜锣山"));
//求合
int sum = list.stream().mapToInt(t -> t.getStuNo()).sum();
//求平均值
OptionalDouble average = list.stream().mapToInt(t -> t.getStuNo()).average();
//求最大值
OptionalInt max = list.stream().mapToInt(t -> t.getStuNo()).max();
//求最小值
OptionalInt min = list.stream().mapToInt(t -> t.getStuNo()).min();
//统计个数
long count = list.stream().mapToInt(t -> t.getStuNo()).count();
System.out.println(sum);
System.out.println(average.getAsDouble());
System.out.println(max.getAsInt());
System.out.println(min.getAsInt());
System.out.println(count);
}
}
IntSummaryStatistics collect = list.stream().collect(Collectors.summarizingInt(s -> s.getStuNo()));
代码语言:javascript复制import java.util.*;
import java.util.stream.Collectors;
public class Demo3 {
public static void main(String[] args) {
List<Student> list=new ArrayList<>();
list.add(new Student(1,"张鹏","男","13312345678","重庆市沙坪坝区"));
list.add(new Student(2,"谢灵儿","女","13311111111","重庆市江北区观音桥"));
list.add(new Student(6,"冯小龙","男","1332222222","重庆市渝北区人和"));
list.add(new Student(4,"蔡金恩","女","1888888888","重庆市北碚区西南大学"));
list.add(new Student(25,"王浩月","女","1323333333","重庆市渝中区解放碑"));
list.add(new Student(19,"姜春阳","女","1555555555","黑龙江省哈尔滨市九龙坡区石桥铺"));
list.add(new Student(16,"陈朋","男","1777777777","重庆市南岸区南坪"));
list.add(new Student(88,"王政","男","1399999999","重庆市巴南区李家沱"));
list.add(new Student(39,"浩楠哥","男","16666666666","重庆市九龙区铜锣山"));
list.add(new Student(39,"浩楠哥111","女","16666666666","重庆市九龙区铜锣山"));
//求合
IntSummaryStatistics collect = list.stream().collect(Collectors.summarizingInt(s -> s.getStuNo()));
System.out.println(collect.getMax());
System.out.println(collect.getMin());
System.out.println(collect.getCount());
System.out.println(collect.getSum());
System.out.println(collect.getAverage());
}
}
sorted() 自然排序,自然排序就是排序的数据类中实现了 Comparable接口
代码语言:javascript复制List<Student> collect = list.stream().sorted().collect(Collectors.toList());
collect.forEach(System.out::println);
sorted(Comparator<? super T> comparator); 使用Comparator接口参数来实现排序
代码语言:javascript复制List<Student> collect = list.stream().sorted((o1,o2)->o1.getStuNo()-o2.getStuNo()).collect(Collectors.toList());
collect.forEach(System.out::println);
findFirst() 获取第一个对象
代码语言:javascript复制Optional<Student> first = list.stream().filter(s -> s.getStuNo() % 2 == 0).findFirst();
System.out.println(first.get());
18.7 Optional
Optional 类是一个可以为null的容器对象,很好的解决空指针异常的烦恼
代码语言:javascript复制isPresent() // 如果对象内部有值返回true,没有值返回false
代码语言:javascript复制first.get() //如果在这个Optional中包含这个值,返回值,否则抛出异常:NoSuchElementException
代码语言:javascript复制//对象内部有值就返回具体的值,如果没有值就返回一个指定的值 orElse(中就是指定的值)
first.orElse(new Student(-1, "没有值", "未知", "00000000000", "000000000"))
代码语言:javascript复制//如果对象内部有值就做Consumer接口中的操作,如果没有值就什么事情也不做
first.ifPresent(f->{ System.out.println(f.getStuName()); });
代码语言:javascript复制Optional<Integer> optional=Optional.empty(); //这是创建一个元素为null的对象
代码语言:javascript复制Optional<Integer> optional=Optional.of(10);//创建一个元素为指定值的对象
代码语言:javascript复制public class Demo3 {
public static void main(String[] args) {
List<Student> list=new ArrayList<>();
list.add(new Student(1,"张鹏","男","13312345678","重庆市沙坪坝区"));
list.add(new Student(2,"谢灵儿","女","13311111111","重庆市江北区观音桥"));
list.add(new Student(6,"冯小龙","男","1332222222","重庆市渝北区人和"));
list.add(new Student(4,"蔡金恩","女","1888888888","重庆市北碚区西南大学"));
list.add(new Student(25,"王浩月","女","1323333333","重庆市渝中区解放碑"));
list.add(new Student(19,"姜春阳","女","1555555555","黑龙江省哈尔滨市九龙坡区石桥铺"));
list.add(new Student(16,"陈朋","男","1777777777","重庆市南岸区南坪"));
list.add(new Student(88,"王政","男","1399999999","重庆市巴南区李家沱"));
list.add(new Student(39,"浩楠哥","男","16666666666","重庆市九龙区铜锣山"));
list.add(new Student(39,"浩楠哥111","女","16666666666","重庆市九龙区铜锣山"));
List<Student> collect = list.stream().filter(s -> s.getStuNo() % 2 == 0).collect(Collectors.toList());
collect.forEach(System.out::println);
System.out.println("======================================================");
Optional<Student> first = list.stream().filter(s -> s.getStuNo() % 9 == 0).findFirst();
//判断是否有值
System.out.println(first.isPresent());
//获取值
System.out.println(first.get());
//对象内部有值就返回具体的值,如果没有值就返回一个指定的值 orElse(中就是指定的值)
System.out.println(first.orElse(new Student(-1, "没有值", "未知", "00000000000", "000000000")));
//如果对象内部有值就做Consumer接口中的操作,如果没有值就什么事情也不做
first.ifPresent(f->{ System.out.println(f.getStuName()); });
//这是创建一个元素为null的对象
Optional<Integer> optional=Optional.empty();
System.out.println(optional.get());
//创建一个元素为指定值的对象
Optional<Integer> optional1=Optional.of(10);
System.out.println(optional1.get());
}
}
18.8 新时间
- 非线程安全 − java.util.Date 是非线程安全的,所有的日期类都是可变的,这是Java日期类最大的问题之一。
- 设计很差
- 时区处理麻烦 − 日期类并不提供国际化,没有时区支持,因此Java引入了java.util.Calendar和java.util.TimeZone类,但他们同样存在上述所有的问题。
TimeZone 老时间中的时区类
代码语言:javascript复制TimeZone timeZone=TimeZone.getTimeZone("GMT 8:00"); //在世界上任何一台服务上设置这个时间点,时间都会到东八区上
TimeZone.setDefault(timeZone);//设置进jvm中
Date date=new Date();
DateFormat dateFormat=new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
System.out.println(dateFormat.format(date));
//这里的时间打印信息与上面的时间有关系
代码语言:javascript复制public class Demo1 {
public static void main(String[] args) {
/*
TimeZone.getTimeZone(ZoneId.of("Asia/Shanghai")) 这里是按时区的ID名在进行设置,中国的标准时间外国人对标的是上海 (Asia/Shanghai)
*/
TimeZone timeZone1 = TimeZone.getTimeZone(ZoneId.of("Asia/Shanghai"));
TimeZone.setDefault(timeZone1);
System.out.println(timeZone1.getID());
Date date=new Date();
DateFormat dateFormat=new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
System.out.println(dateFormat.format(date));
}
}
- LocalDateTime (日期 时间), LocalDate(日期), LocalTime(时间)
public class Demo2 {
public static void main(String[] args) {
//创建一个系统现在时间
LocalDateTime localDateTime=LocalDateTime.now();
System.out.println(localDateTime);//2022-07-06T15:10:28.275 ISO8601国际时间标准
//取年
System.out.println(localDateTime.getYear());
//取月
System.out.println(localDateTime.getMonthValue());
//getMonth()获取的是月份对象 Month类
System.out.println(localDateTime.getMonth().getValue());
//取日期 getDayOfMonth 这个月中的这一天是什么值
System.out.println(localDateTime.getDayOfMonth());
//取小时
System.out.println(localDateTime.getHour());
//取分钟
System.out.println(localDateTime.getMinute());
//取秒
System.out.println(localDateTime.getSecond());
System.out.println("=============================================");
Calendar calendar=Calendar.getInstance();
System.out.println(calendar.get(Calendar.YEAR));
System.out.println(calendar.get(Calendar.MONTH) 1);
System.out.println(calendar.get(Calendar.DAY_OF_MONTH));
System.out.println(calendar.get(Calendar.HOUR));
System.out.println(calendar.get(Calendar.MINUTE));
System.out.println(calendar.get(Calendar.SECOND));
}
}
创建指定时间和格式化
代码语言:javascript复制package com.qf.dateDemo;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
public class Demo3 {
public static void main(String[] args) {
//创建指定时间
LocalDateTime of = LocalDateTime.of(2022, 8, 10, 12, 12, 12);
//创建格式化对象
DateTimeFormatter formatter=DateTimeFormatter.ofPattern("yyyy/MM/dd hh/mm/ss");
//格式化时间对象并打印
System.out.println(formatter.format(of));
}
}
对时间进行加操作 plusXXX() XXX代表时间部位的单词
代码语言:javascript复制public class Demo3 {
public static void main(String[] args) {
LocalDateTime now = LocalDateTime.now();
//LocalDateTime是不可改变的时间对象,所以每次对值的改变都是产生一个新的值,不会改变原值和Stirng一样
now= now.plusDays(5);
System.out.println(now);
}
}
对时间进行减操作
代码语言:javascript复制public class Demo3 {
public static void main(String[] args) {
LocalDateTime now = LocalDateTime.now();
now= now.minusMonths(5);
System.out.println(now);
}
}
设置时间某部位的值,withXXX() 对指定的部位的值进行设置
代码语言:javascript复制public class Demo3 {
public static void main(String[] args) {
LocalDateTime now = LocalDateTime.now();
now= now.withDayOfMonth(3).withMonth(9);
System.out.println(now);
}
}
获取时间戳
代码语言:javascript复制import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
public class Demo3 {
public static void main(String[] args) {
//设置指定时间
LocalDateTime of = LocalDateTime.of(2020,6,4,12,12,12);
// 设置时区 toEpochSecond()获取时间戳
long l = of.atOffset(ZoneOffset.ofHours(8)).toEpochSecond();
System.out.println(l);
System.out.println(System.currentTimeMillis());
}
}
瞬时时间点对象
代码语言:javascript复制public class Demo4 {
public static void main(String[] args) {
LocalDateTime of = LocalDateTime.of(2020,6,4,12,12,12);
//Instant瞬时时间点对象 of.toInstant(设置时区)
Instant instant=of.toInstant(ZoneOffset.ofHours(8));
//toEpochMilli() 获取时间戳
System.out.println(instant.toEpochMilli());
}
}
18.9结语
谢谢观看,这一节花了我一个早上的时间整理出来的,希望大家能有所收获!!!谢谢大家的支持!!!