Java8新特性
接口中默认方法修饰为普通方法
lambda表达式
函数是式接口编程
方法与构造函数引用 类名称::方法名称
Stream接口
接口中默认方法修饰为普通方法
在JDK 1.8开始 支持使用static和default 修饰 可以写方法体,不需要子类重写。
方法:
普通方法 可以有方法体
抽象方法 没有方法体需要子类实现 重写。
注:接口中的属性的默认是public static final 、方法是public abstract
使用jdk8新特性可以定义普通方法,用default或者static修饰
public interface Jdk8Interface {
void add();
default void getDefault(){
System.out.println("helo");
}
static void delStatic(){
System.out.println("static");
}
}
lambda表达式
lambda表达式的好处:简化了匿名内部类的调用
1.使用匿名内部类的形式调用接口
public class Test1 {
public static void main(String[] args) {
new OrderService() {
@Override
public void get() {
System.out.println("get");
}
}.get();
}
}
Lambda+方法引入代码变得更加精简
Lambda表达式的规范
使用Lambda表达式 依赖于函数接口
-
在接口中只能够允许有一个抽象方法
-
在函数接口中定义object类中方法
-
使用默认或者静态方法
-
@FunctionalInterface 表示该接口为函数接口
Java中使用Lambda表达式的规范,必须是为函数接口
函数接口的定义:在该接口中只能存在一个抽象方法,该接口称作为函数接口
JDK中自带的函数接口:
java.lang.Runnable
java.util.concurrent.Callable
java.security.PrivilegedAction
java.util.Comparator
java.io.FileFilter
java.nio.file.PathMatcher
java.lang.reflect.InvocationHandler
java.beans.PropertyChangeListener
java.awt.event.ActionListener
javax.swing.event.ChangeListener
我们也可以使用@FunctionalInterface修饰为函数接口
使用Lambda方法体中只有一条语句的情况下,在这时候我们不需要写(也可以不需要写return
使用forEach遍历集合
public class Test4 {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
list.add("chen");
list.add("zhang");
list.add("wang");
list.forEach(new Consumer<String>() {
@Override
public void accept(String s) {
System.out.println(s);
}
});
//升级版本
list.forEach(s->{
System.out.println(s);
});
}
}
小试牛刀:对集合进行排序
public class Test5 {
public static void main(String[] args) {
ArrayList<User> list = new ArrayList<>();
list.add(new User("小米",20));
list.add(new User("小华",15));
list.add(new User("小陈",23));
list.sort(new Comparator<User>() {
@Override
public int compare(User o1, User o2) {
return o1.getAge()-o2.getAge();
}
});
list.sort((o1,o2)->
o1.getAge()-o2.getAge()
);
list.forEach((t)->{
System.out.println(t.toString());
});
}
}
线程调用
new Thread(()-> System.out.println("我是子线程")).start();
什么是stream流
Stream 是JDK1.8 中处理集合的关键抽象概念,Lambda 和 Stream 是JDK1.8新增的函数式编程最有亮点的特性了,它可以指定你希望对集合进行的操作,可以执行非常复杂的查找、过滤和映射数据等操作。使用Stream API 对集合数据进行操作,就类似于使用SQL执行的数据库查询。Stream 使用一种类似用 SQL 语句从数据库查询数据的直观方式来提供一种对 Java 集合运算和表达的高阶抽象。Stream API可以极大提高Java程序员的生产力,让程序员写出高效率、干净、简洁的代码。
这种风格将要处理的元素集合看作一种流, 流在管道中传输, 并且可以在管道的节点上进行处理, 比如筛选, 排序,聚合等。
元素流在管道中经过中间操作(intermediate operation)的处理,最后由最终操作(terminal operation)得到前面处理的结果。
Stream :非常方便精简的形式遍历集合实现 过滤、排序等。
Mysql:select userName from xxwhere userName =‘xx’
Order by age limt(0,2)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nQ2jDxaN-1642494256991)(file:///C:\Users\chenchao\AppData\Local\Temp\ksohtml\wpsC252.tmp.jpg)]
Stream创建方式
parallelStream为并行流采用多线程执行
Stream采用单线程执行
parallelStream效率比Stream要高。
实体类
public class User {
private String username;
private int age;
public User(String username, int age) {
this.username = username;
this.age = age;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public User() {
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "User{" +
"username='" + username + '\'' +
", age=" + age +
'}';
}
@Override
public boolean equals(Object o) {
if (o instanceof User){
return username.equals(((User) o).username) && age==(((User) o).age);
}else {
return false;
}
}
@Override
public int hashCode(){
return username.hashCode();
}
}
实例
public class Test7 {
public static void main(String[] args) {
ArrayList<User> userEntities = new ArrayList<>();
userEntities.add(new User("mayikt", 20));
userEntities.add(new User("meite", 28));
userEntities.add(new User("zhangsan", 35));
userEntities.add(new User("xiaowei", 16));
userEntities.add(new User("xiaowei", 16));
/*串行流 Stream() 单线程
* 并行流parsellerStream() 多线程*/
Stream<User> stream = userEntities.stream();
// 将List集合转换为set集合类型
Set<User> userSet = stream.collect(Collectors.toSet());
userSet.forEach((user) -> {
System.out.println(user.toString());
});
}
}
set集合底层依赖于map集合实现防重复key map集合底层基于equals比较防重复的
new FunctionUserEntity(list集合中的类型),String(key map)>
使用stream流将list集合转换为并遍历map集合
public class Test8 {
public static void main(String[] args) {
ArrayList<User> arrayList = new ArrayList<>();
arrayList.add(new User("hello", 20));
arrayList.add(new User("小华", 19));
arrayList.add(new User("小美", 21));
arrayList.add(new User("小张", 22));
Stream<User> stream = arrayList.stream();
/**
* new FunctionUserEntity(list集合中的类型),String(key map)>
*/
Map<String, User> collect = stream.collect(Collectors.toMap(new Function<User, String>() {
@Override
public String apply(User user) {
return user.getUsername();
}
}, new Function<User, User>() {
@Override
public User apply(User user) {
return user;
}
}));
//遍历
collect.forEach(new BiConsumer() {
@Override
public void accept(Object o, Object o2) {
System.out.println(o+","+o2);
}
});
//使用lamdba表达式
Map<String, User> collect = stream.collect(Collectors.toMap(user -> user.getUsername(), user -> user));
//遍历
collect.forEach((BiConsumer) (o, o2) -> System.out.println(o+","+o2));
}
}
stream流求和
public class Test9 {
public static void main(String[] args) {
Stream<Integer> stream = Stream.of(10, 20, 30, 40, 50);
/*Optional<Integer> reduce = stream.reduce(new BinaryOperator<Integer>() {
@Override
public Integer apply(Integer a1, Integer a2) {
return a1 + a2;
}
});
System.out.println(reduce.get());
*/
Optional<Integer> reduce = stream.reduce((BinaryOperator<Integer>) (a1, a2) ->
a1 + a2
);
System.out.println(reduce.get());
}
}
取出最大值
public class Test10 {
public static void main(String[] args) {
ArrayList<User> arrayList = new ArrayList<>();
arrayList.add(new User("hello", 20));
arrayList.add(new User("小华", 19));
arrayList.add(new User("小美", 21));
arrayList.add(new User("小张", 22));
Stream<User> stream = arrayList.stream();
Optional<User> max = stream.max(new Comparator<User>() {
@Override
public int compare(User o1, User o2) {
return o1.getAge() - o2.getAge();
}
});
System.out.println(max.get());
}
}
StreamMatch匹配
anyMatch表示,判断的条件里,任意一个元素成功,返回true
allMatch表示,判断条件里的元素,所有的都是,返回true
noneMatch跟allMatch相反,判断条件里的元素,所有的都不是,返回true
anyMatch 匹配一条含有的数据
public class Test11 {
public static void main(String[] args) {
ArrayList<User> arrayList = new ArrayList<>();
arrayList.add(new User("hello", 20));
arrayList.add(new User("小华", 19));
arrayList.add(new User("小美", 21));
arrayList.add(new User("小张", 22));
Stream<User> stream = arrayList.stream();
boolean b = stream.anyMatch(new Predicate<User>() {
@Override
public boolean test(User user) {
return "hello".equals(user.getUsername());
}
});
System.out.println(b);
}
}
allMatch 匹配所有必须含有的数据
stream过滤器
public class Test12 {
public static void main(String[] args) {
ArrayList<User> arrayList = new ArrayList<>();
arrayList.add(new User("hello", 20));
arrayList.add(new User("小华", 19));
arrayList.add(new User("小华", 17));
arrayList.add(new User("小美", 21));
arrayList.add(new User("小张", 22));
Stream<User> stream = arrayList.stream();
stream.filter(new Predicate<User>() {
@Override
public boolean test(User user) {
return "小华".equals(user.getUsername()) &&user.getAge()>18;
}
}).forEach((t)-> System.out.println(t));
}
}
Stream limit和 skip(跳出)
public class Test13 {
public static void main(String[] args) {
ArrayList<User> arrayList = new ArrayList<>();
arrayList.add(new User("hello", 20));
arrayList.add(new User("小华", 19));
arrayList.add(new User("小华", 17));
arrayList.add(new User("小美", 21));
arrayList.add(new User("小张", 22));
Stream<User> stream = arrayList.stream();
Stream<User> limit = stream.skip(2).limit(2);
limit.forEach((t)->{
System.out.println(t);
});
}
}
stream流排序
public class Test14 {
public static void main(String[] args) {
ArrayList<User> arrayList = new ArrayList<>();
arrayList.add(new User("hello", 20));
arrayList.add(new User("小华", 19));
arrayList.add(new User("小华", 17));
arrayList.add(new User("小美", 21));
arrayList.add(new User("小张", 22));
Stream<User> stream = arrayList.stream();
stream.sorted(new Comparator<User>() {
@Override
public int compare(User o1, User o2) {
return -(o1.getAge()-o2.getAge()); //降序
}
}).forEach((t)->{
System.out.println(t);
});
}
}
综合案列:对数据流的数据实现降序排列、小华 获取前两位
public class Test15 {
public static void main(String[] args) {
ArrayList<User> arrayList = new ArrayList<>();
arrayList.add(new User("hello", 20));
arrayList.add(new User("小华", 19));
arrayList.add(new User("demo_zhangsan", 17));
arrayList.add(new User("demo", 18));
arrayList.add(new User("demo_lisi", 17));
arrayList.add(new User("小美", 21));
arrayList.add(new User("小张", 22));
Stream<User> stream = arrayList.stream();
//要求:对数据流的数据实现降序排列、小华 获取前两位
stream.sorted(new Comparator<User>() {
@Override
public int compare(User o1, User o2) {
return o2.getAge()-o1.getAge();
}
}).filter(new Predicate<User>() {
@Override
public boolean test(User user) {
return "demo".equals(user.getUsername());
}
}).limit(2).forEach((t)->{
System.out.println(t);
});
}
}
串行流求速度
public class Test16 {
public static void main(String[] args) {
Instant start = Instant.now();
long sum = 0;
for (long i = 0; i < 500000000L; i++) {
sum += i;
}
System.out.println(sum);
Instant end = Instant.now();
System.out.println("花费的时间是:" + Duration.between(start, end).toMillis());
}
}
并行流
Instant start = Instant.now();
LongStream longStream = LongStream.rangeClosed(0, 5000000000L);
OptionalLong reduce = longStream.parallel().reduce(new LongBinaryOperator() {
@Override
public long applyAsLong(long left, long right) {
return left + right;
}
});
System.out.println(reduce);
Instant end = Instant.now();
System.out.println("花费的时间是:" + Duration.between(start, end).toMillis());
并行流与串行流区别
串行流:单线程的方式操作; 数据量比较少的时候。
并行流:多线程方式操作;数据量比较大的时候,原理:
Fork join 将一个大的任务拆分n多个小的子任务并行执行,
最后在统计结果,有可能会非常消耗cpu的资源,确实可以
提高效率。
注意:数据量比较少的情况下,不要使用并行流。
方法引入
什么是方法引入
方法引入:需要结合lambda表达式能够让代码变得更加精简。
-
匿名内部类使用
-
Lambda调用匿名内部类
-
方法引入
方法引入
-
静态方法引入: 类名::(静态)方法名称
-
对象方法引入 类名:: 实例方法名称
-
实例方法引入 new对象 对象实例::方法引入
-
构造函数引入 类名::new
需要遵循一个规范:
方法引入 方法参数列表、返回类型与函数接口参数列表与返回类型必须
要保持一致。
Lambda: 匿名内部类使用代码简洁问题。
类型 | 语法 | 对应lambda表达式 |
---|---|---|
构造器引用 | Class::new | (args) -> new 类名(args) |
静态方法引用 | Class::static_method | (args) -> 类名.static_method(args) |
对象方法引用 | Class::method | (inst,args) -> 类名.method(args) |
实例方法引用 | instance::method | (args) -> instance.method(args) |
方法引用提供了非常有用的语法,可以直接引用已有的java类或对象的方法或构造器。方法引用其实也离不开Lambda表达式,
与lambda联合使用 ,方法引用可以使语言的构造更加紧凑简洁,减少冗余代码。
方法引用提供非常有用的语法,可以直接引用已有的java类或者对象中方法或者构造函数,
方法引用需要配合Lambda表达式语法一起使用减少代码的冗余性问题。
构造器引入
静态方法引入
对象方法引入
实例方法引入
方法引入规则
方法引入实际上就是lambda表达式中直接引入的方法。
必须遵循规范:引入的方法参数列表返回类型必须要和函数接口参数列表、返回
类型保持一致。
public class Test1 {
public static void main(String[] args) {
// 最原生的匿名内部类
/* MessageInterface messageInterface = new MessageInterface() {
@Override
public void get(Integer a) {
System.out.println("get:a:"+a);
}
};
messageInterface.get(1);*/
/* MessageInterface messageInterface1 = (a)->{
Test1.staticGet(a);
};
messageInterface1.get(2);*/
MessageInterface staticGet = Test1::staticGet;
staticGet.get(12);
}
public static void staticGet(Integer a) {
System.out.println("staticGet:a:" + a);
}
}
实例方法引入
public class Test2 {
public static void main(String[] args) {
Test2 test2 = new Test2();
MessageInterface messageInterface=()->
test2.objGet();
System.out.println(messageInterface.get());
MessageInterface messageInterface1=test2::objGet;
}
public String objGet(){
return "chen";
}
}
对象实例
public class Test3 {
public static void main(String[] args) {
/* MessageInterFace2 messageInterFace2=()->{
return new Message();
};*/
MessageInterFace2 messageInterFace2 = Message::new;
System.out.println(messageInterFace2.getMsg());
Function<String,Integer> s=(str)->{
return str.length();
};
Function<String,Integer> str=String::length;
}
}
Optional
Optional 类是一个可以为null的容器对象。如果值存在则isPresent()方法会返回true,调用get()方法会返回该对象。
Optional 是个容器:它可以保存类型T的值,或者仅仅保存null。Optional提供很多有用的方法,这样我们就不用显式进行空值检测。
Optional 类的引入很好的解决空指针异常。
判断参数是否为空
ofNullable(可以传递一个空对象)
Of(不可以传递空对象)
public class Test4 {
public static void main(String[] args) {
String username=null;
Optional<String> optional = Optional.ofNullable(username);
boolean present = optional.isPresent();//判断是否为空
System.out.println(present);
}
}
参数实现过滤,参数为空可以设定默认值
public class Test4 {
public static void main(String[] args) {
String username=null;
/* Optional<String> optional = Optional.ofNullable(username);
boolean present = optional.isPresent();//判断是否为空
System.out.println(present);*/
/* String chen = Optional.ofNullable(username).orElse("chen"); //orElse设定默认值*/
Optional<String> chen = Optional.ofNullable(username).filter(new Predicate<String>() {
@Override
public boolean test(String s) {
return s.equals("chen");
}
});
System.out.println(chen.isPresent());
}
}
方法引入
public class Test5 {
public static void main(String[] args) {
String username=null;
Optional<String> username1 = Optional.ofNullable(username);
boolean present = username1.isPresent();
if (present){
System.out.println(username1.get());
}
/* username1.ifPresent(new Consumer<String>() {
@Override
public void accept(String s) {
System.out.println(s);
}
});*/
// 方法引入
username1.ifPresent(System.out::print);
}
}
orElseGet()—与函数的接口的形式赋默认值
orELse()----直接传递默认值
return s.equals(“chen”);
}
});
System.out.println(chen.isPresent());
}
}
### 方法引入
public class Test5 {
public static void main(String[] args) {
String username=null;
Optional username1 = Optional.ofNullable(username);
boolean present = username1.isPresent();
if (present){
System.out.println(username1.get());
}
/* username1.ifPresent(new Consumer() {
@Override
public void accept(String s) {
System.out.println(s);
}
});*/
// 方法引入
username1.ifPresent(System.out::print);
}
}
orElseGet()---与函数的接口的形式赋默认值
orELse()----直接传递默认值