目录
1、Optional容器
package com.xch.feature01;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.function.Function;
/**
* @author Chenghe Xu
* @date 2022/7/22 11:11
*/
public class Test05 {
public static void main(String[] args) {
/**
* Java 8引入Optional类来防止空指针异常
* Optional类实际上是个容器:它可以保存类型T的值,或者保存null
* 使用Optional类我们就不用显式进行空指针检查了
*/
//Optional产生对象的of()、ofNullable()方法的使用和区别:
//of()是指返回一个Optional包含的非null值对象
Optional<String> optional1=Optional.of("原测试值001");
//ofNullable()是指返回一个Optional包含的可为null值对象
Optional<String> optional2=Optional.ofNullable(null);
//Optional判断orElse()、orElseGet()方法的使用和区别:
//orElse()是指Optional对象如果非null,则返回该值,否则返回other值或函数执行结果
//orElse()方法缺点:orElse里的函数一定会执行,但是结果是由orElse()方法选择输出
System.out.println(optional1.orElse(createTest()));
System.out.println(optional2.orElse(createTest()));
System.out.println("============================");
//orElseGet()是指Optional对象如果非null,则返回该值,否则返回lambda匿名表达式执行结果
System.out.println(optional1.orElseGet( Test05::createTest ));
System.out.println(optional2.orElseGet( () -> createTest() ));
//orElseThrow()方法的使用,不为null则输出,否则报自定义的异常信息
System.out.println("---------------------------");
System.out.println(optional1.orElseThrow(()->new IllegalArgumentException("this optional is empty")));
// System.out.println(optional2.orElseThrow(()->new IllegalArgumentException("this optional is empty")));
Optional<Person> optional3=Optional.ofNullable(new Person("小徐",21));
Optional<Person> optional4=Optional.ofNullable(null);
//Optional的isPresent()方法使用
//用来验证Optional实例中的值是否有值,有值返回true,若为null则返回false
System.out.println(optional3.isPresent());
System.out.println(optional4.isPresent());
//Optional的ifPresent()方法使用
//是一种函数式编程接口:如果Optional中为非null,则调用consumer函数
optional3.ifPresent(person -> person.func1());
optional3.ifPresent(Person::func1);
optional3.ifPresent(person -> Person.func2(person));
optional3.ifPresent(Person::func2);
//Optional为null,则不输出
optional4.ifPresent(Person::func2);
//Optional的ifPresentOrElse()方法使用
//是一种函数式编程接口:如果Optional中为非null,则调用前面consumer函数
optional3.ifPresentOrElse(Person::func1,Person::func3);
//Optional为null,则调用后面的runnable函数
optional4.ifPresentOrElse(Person::func2,Person::func3);
//Optional的map()方法使用(传入匿名函数的参数:一个调用对象T,一个出参R)
//map方法可以实现对Optional实例进行连续操作,如果optional中有值,就调用mapping函数得到返回值
System.out.println(optional3.map(x1->x1.getName()));
System.out.println(optional3.map(Person::getName));
Person p1=new Person("小军", 23);
System.out.println(optional3.map(x3 -> p1.getName()));
System.out.println(optional3.map(x4->x4.func4("测试")));
System.out.println(optional3.map(x5->Person.func5("测试")));
System.out.println(optional3.map(x6->x6.func6()));
System.out.println(optional3.map(Person::func6));
System.out.println(optional3.map(x7->Person.func7()));
//Optional为null,则调用后面的orElse/orElseGet函数
System.out.println(optional4.map(x6->x6.func6()).orElse("Optional对象为null"));
System.out.println(optional4.map(Person::func6).orElseGet(p1::func6));
System.out.println(optional4.map(Person::func6).orElseGet(()->p1.func6()));
System.out.println(optional4.map(Person::func6).orElseGet(Person::func7));
System.out.println(optional4.map(Person::func6).orElseGet(()->Person.func7()));
//综合测试
//其中,ls.size()>x是判断表达式,返回结果为true/false
//Optional.map()不为null时,orElse/orElseGet函数不影响执行结果,仅为了让返回参数为Boolean
//Optional.map()为null时,返回orElse/orElseGet函数执行结果,否则返回Optional.empty
List<String> list1 = Arrays.asList("aa", "bb", "cc");
List<String> list2 = null;
Optional<Boolean> flag1 = Optional.ofNullable(list1).map(ls -> ls.size() >= 4);
Optional<Boolean> flag2 = Optional.ofNullable(list2).map(ls -> ls.size() >= 4);
Boolean flag3 = Optional.ofNullable(list1).map(ls -> ls.size() >= 4).orElse(false);
Boolean flag4 = Optional.ofNullable(list1).map(ls -> list1.size() >= 4).orElse(true);
//Optional.ofNullable()返回null后,直接执行orElse/orElseGet函数,不执行map函数
Boolean flag5 = Optional.ofNullable(list2).map(ls -> list2 == null).orElse(true);
//Optional<T>和T类型转换方法
//T转Optional<T>方法:of/ofNullable(of方法null会报错)
//Optional<T>转T方法:get/orElse/orElseGet(get方法null会报错)
Optional<Boolean> flag6 = Optional.ofNullable(flag5);
Boolean flag7 = flag6.get();
Optional<Integer> flag8 = Optional.ofNullable(list1).map(List::size);
Optional<String> flag9 = Optional.ofNullable(list1).map(ls -> ls.get(2));
Integer flag10 = Optional.ofNullable(list2).map(List::size).orElse(999);
System.out.println(flag1);
System.out.println(flag2);
System.out.println(flag3);
System.out.println(flag4);
System.out.println(flag5);
System.out.println(flag6);
System.out.println(flag7);
System.out.println(flag8);
System.out.println(flag9);
System.out.println(flag10);
System.out.println("=====================");
//可以通过map一直判空
//map中输入的功能函数不能为null,输入的功能函数结果可以为null
Person person11 = null;
Person person12 = new Person();
Person person13 = new Person("XIAO",21);
System.out.println(Optional.ofNullable(person11).map(Person::getName));
System.out.println(Optional.ofNullable(person12).map(Person::getName));
System.out.println(Optional.ofNullable(person13).map(Person::getName));
System.out.println(Optional.ofNullable(person11).map(Person::getName).orElse("出现null"));
System.out.println(Optional.ofNullable(person12).map(Person::getName).orElse("出现null"));
System.out.println(Optional.ofNullable(person13).map(Person::getName).orElse("出现null"));
//可以通过map一直判空,返回Boolean
//其中orElse方法对应ofNullable返回null执行的
//map方法直接输出true/false
//因此,第四个true是orElse输出的,第五/六个true是map输出的
System.out.println(Optional.ofNullable(person11).map(person->Objects.isNull(person.getName())));
System.out.println(Optional.ofNullable(person12).map(person->Objects.isNull(person.getName())));
System.out.println(Optional.ofNullable(person13).map(person->Objects.isNull(person.getName())));
System.out.println(Optional.ofNullable(person11).map(person->Objects.isNull(person.getName())).orElse(true));
System.out.println(Optional.ofNullable(person12).map(person->Objects.isNull(person.getName())).orElse(true));
System.out.println(Optional.ofNullable(person13).map(person->Objects.isNull(person.getName())).orElse(true));
}
public static String createTest(){
System.out.println("原测试值为null--生产一个对象");
return "新测试值002";
}
}
@Data
@NoArgsConstructor
@AllArgsConstructor
class Person{
String name;
Integer age;
public void func1(){
System.out.println("执行lambda函数1");
}
public static void func2(Person person){
System.out.println("执行lambda函数2"+"--"+person);
}
public static void func3(){
System.out.println("执行lambda函数3");
}
public String func4(String str){
return "返回出参4"+"--"+str;
}
public static String func5(String str){
return "返回出参5"+"--"+str;
}
public String func6(){
return "返回出参6";
}
public static String func7(){
return "返回出参7";
}
}
2、Stream流
package com.xch.feature01;
import cn.hutool.core.collection.CollectionUtil;
import lombok.AllArgsConstructor;
import lombok.Data;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;
/**
* @author Chenghe Xu
* @date 2022/7/26 11:50
*/
class Test07 {
public static void main(String[] args) {
List<Integer> list= Arrays.asList(6,6,7,8,8,9);
System.out.println(list);
//Stream去重
List<Integer> list1=list.stream().distinct().collect(Collectors.toList());
System.out.println(list1);
//stream过滤
List<Integer> list2=list.stream().filter(x->x==9).collect(Collectors.toList());
List<Integer> list3=list.stream().filter(x->x==19).collect(Collectors.toList());
System.out.println(list2);
System.out.println(list3);
System.out.println(Optional.ofNullable(list2.size()==0?null:list2.get(0)).orElseGet(()->null));
System.out.println(Optional.ofNullable(list3.size()==0?null:list3.get(0)).orElseGet(()->null));
System.out.println(list2.size()==0?null:list2.get(0));
System.out.println(list3.size()==0?null:list3.get(0));
}
}
/**
* @author Chenghe Xu
* @date 2022/7/26 16:56
*
* 校验类汇总
* null方法是判断null
* empty方法是判断null、空串
* blank方法是判断null、空串、空格串
*
* 字符串判null、空串、空格串
*
* 集合产生空集合以及判断空集合
*/
class Test08 {
public static void main(String[] args) {
String str1=null;
String str2="";
String str3=" ";
//1、hutool的StrUtil类、ObjectUtil类、CollectionUtil类(常用)
//isEmpty()方法判断null、空串
//isBlank()方法判断null、空串、空格串
//2、java的Collections类(常用)
//3、springframework的Objects类、ObjectUtils类、StringUtils类、CollectionUtils类
//测试集合拆分方法
List<Integer> list = Arrays.asList(2, 2, 4, 4, 5, 6, 7, 8, 9);
List<List<Integer>> split = CollectionUtil.split(list, 2);
split.forEach(x->System.out.println(x));
split.forEach(System.out::println);
//Stream转List集合
List<Integer> list1 = list.stream().collect(Collectors.toList());
System.out.println(list1);
//List集合转Set集合(去重)
Set<Integer> set = list.stream().collect(Collectors.toSet());
System.out.println(set);
//List集合转Map集合(先去重)
Map<Integer, Integer> map_1 = list.stream().distinct().collect(Collectors.toMap(x -> x, x -> x));
Map<Integer, Integer> map_2 = list.stream().distinct().collect(Collectors.toMap(x -> x, x -> 2*x));
Map<Integer, Integer> map_3 = list.stream().distinct().collect(Collectors.toMap(x -> x-1, x -> 2*x));
System.out.println(map_1);
System.out.println(map_2);
System.out.println(map_3);
//Arrays数组转Map集合(先去重或选择带重复处理的转Map方法)
Integer[] arr = new Integer[]{22,22,33,44,55,55,66,77};
Map<Integer, Integer> integerMap1 = Arrays.stream(arr).distinct().collect(Collectors.toMap(x -> x, Function.identity()));
//mergeFunction参数传入(x1, x2) -> x1,代表重复则选第一个为key覆盖第二个key
Map<Integer, Integer> integerMap2 = Arrays.stream(arr).collect(Collectors.toMap(x -> x, Function.identity(), (x1, x2) -> x1));
System.out.println(integerMap1);
System.out.println(integerMap2);
//Function.identity()方法等于x->x,x->{return x;}即为原输出
Map<Integer, Integer> map_4 = list.stream().distinct().collect(Collectors.toMap(x -> x, Function.identity()));
System.out.println(map_4);
//第三个参数mergeFunction提供重复key处理
Map<Integer, Integer> map_5 = list.stream().collect(Collectors.toMap(x -> x, x -> x,(k1,k2)->k1+k2));
System.out.println(map_5);
//List集合转Map集合(分类)
Map<Integer, List<Integer>> map1 = list.stream().collect(Collectors.groupingBy(x -> x));
Map<Integer, List<Integer>> map2 = list.stream().collect(Collectors.groupingBy(x -> x+1));
Map<Integer, List<Integer>> map3 = list.stream().collect(Collectors.groupingBy(x -> {return x;}));
System.out.println(map1);
System.out.println(map2);
System.out.println(map3);
//判断表达式分类
Map<Boolean, List<Integer>> map4 = list.stream().collect(Collectors.partitioningBy(x->x>=4));
Map<Boolean, List<Integer>> map5 = list.stream().collect(Collectors.partitioningBy(Predicate.isEqual(4)));
System.out.println(map4);
System.out.println(map5);
//高阶综合分类测试
List<User> users = Arrays.asList(new User("employer", 001, "徐老板")
, new User("employee", 002, "何员工")
, new User("employee", 003, "李员工")
, new User("vip", 004, "黄会员")
, new User("vip", 005, "梁会员")
, new User("consumer", 006, "龙顾客")
, new User("consumer", 007, "朱顾客"));
//仅按classify分类,equals()方法判断相等则为同一类
Map<String, List<User>> categories1 = users.stream().collect(Collectors.groupingBy(user -> user.getClassify()));
Map<String, List<User>> categories2 = users.stream().collect(Collectors.groupingBy(user -> fetchGroupKey1(user)));
Map<String, List<User>> categories3 = users.stream().collect(Collectors.groupingBy(Test08::fetchGroupKey1));
System.out.println(categories1);
System.out.println(categories2);
System.out.println(categories3);
//按classify和userId分类,equals()方法判断相等则为同一类
Map<String, List<User>> categories4 = users.stream().collect(Collectors.groupingBy(user -> user.getClassify()+"-"+user.getUserId()));
Map<String, List<User>> categories5 = users.stream().collect(Collectors.groupingBy(user -> Test08.fetchGroupKey2(user)));
Map<String, List<User>> categories6 = users.stream().collect(Collectors.groupingBy(Test08::fetchGroupKey2));
System.out.println(categories4);
System.out.println(categories5);
System.out.println(categories6);
}
//仅按classify分类,equals()方法判断相等则为同一类
private static String fetchGroupKey1(User user){
return user.getClassify();
}
//按classify和userId分类,equals()方法判断相等则为同一类
private static String fetchGroupKey2(User user){
return user.getClassify()+"-"+user.getUserId();
}
}
@Data
@AllArgsConstructor
class User{
private String classify;
private Integer userId;
private String userName;
}
3、Lambda匿名函数
package com.xch.feature01;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
import java.util.function.Consumer;
import java.util.function.Function;
/**
* @author Chenghe Xu
* @date 2022/7/27 12:16
*
* ::引用用法和->实现的区别
*
* ::是指方法引用
* ->是指匿名函数(Lambda)
*
* 方法引用也是一种函数式接口的书写方式,Lambda表达式也是一种函数式接口;
* Lambda表达式一般用于自己提供方法体,而方法引用一般直接引用现成的方法。
*
* 方法引用分为三种,方法引用通过一对双冒号:: 来表示,方法引用是一种函数式接口的另一种书写方式
* 1、静态方法引用,通过类名::静态方法名, 如 Student::say2
* 2、实例方法引用,通过实例对象::实例方法,如 Student::say1、"xxx"::substring
* 3、构造方法引用,通过类名::new, 如 Student::new
*/
public class Test09 {
/**
* 注:要实现@FunctionalInterface注解的接口,才能接收lambda匿名函数
* 如:Supplier<T>、Predicate<T>、Function<T, R>、Consumer<T>、***Operator、Comparator<T>、Runnable
* 其中:Predicate<T>是一个返回true/false的lambda函数表达式
* Comparator<T>是一个比较器的lambda函数表达式
* Runnable是一个无参lambda函数表达式
* 其中:Function<T, R>的T是指调用对象,R出参,因此apply方法有返回值
* BiConsumer<T, U>的T是指调用对象,U是入参,因此accept方法没有返回值
*
* 因此,只有可以接收这些参数的函数才能写lambda表达式
* 能如:Stream.generate(Math::random);
* 不能如:System.out.println(Math::random);
*/
public static void main(String[] args) {
//使用Java默认的6大承接返回功能接口对象(@FunctionalInterface注解的接口)
//目前验最多承接三个参数(调用对象+入参<=2,出参<=1)
//(T:调用对象,U:入参,R:出参)
//调用静态方法参数顺序是:入参、出参
//调用实例方法参数顺序是:调用对象、入参、出参
//调用实例方法也可以用实例对象调用,参数顺序是:入参、出参
//1、使用双冒号::来构造静态函数引用
Consumer<String> say2 = Student::say2;
Function<String, String> say4 = Student::say4;
BiConsumer<Function<String, String>, String> dynamicSay = Student::dynamicSay;
BiConsumer<Student, String> whoSay = Student::whoSay;
BiFunction<Integer, String, String> upper1 = Student::upper1;
//没有返回值void,则用Consumer对象承接,accept调用即可
say2.accept("1Hello xch");
dynamicSay.accept("2Hello "::concat,"xch");
dynamicSay.accept(String::toUpperCase, "3Hello xch");
whoSay.accept(new Student("4小金",20), "Hello");
//有返回值Object,则用Function对象承接,apply调用即可
System.out.println(say4.apply("5Hello xch"));
System.out.println(upper1.apply(006, "小张"));
//2、使用双冒号::来构造非静态函数引用
BiConsumer<Student, String> say1 = Student::say1;
BiFunction<Student, String, String> say3 = Student::say3;
Student student1=new Student();
BiFunction<Integer, String, String> upper2 = student1::upper2;
say1.accept(new Student(),"7Hello xch");
System.out.println(say3.apply(new Student(),"8Hello xch"));
System.out.println(upper2.apply(9, "小杨"));
//3、构造函数引用
BiFunction<String, Integer, Student> obj = Student::new;
Student student2 = obj.apply("10小徐", 21);
System.out.println(student2);
//测试
String content = "Hello JDK8";
Function<Integer, String> func1 = content::substring;
BiFunction<Integer, Integer, String> func2 = content::substring;
System.out.println(func1.apply(2));
System.out.println(func2.apply(2,content.length()-1));
}
}
/**
* final修饰类:
* 使用final修饰类的目的简单明确,表明这个类不能被继承。
* 当程序中有永远不会被继承的类时,可以使用final关键字修饰。
* 被final修饰的类所有成员方法都将被隐式修饰为final方法。
*
* final修饰方法:
* 首要作用是锁定方法,不让任何继承类对其进行修改。
* 另外一个作用是在编译器对方法进行内联,提升效率。
*
* final修饰变量:
* 当final修饰的是一个基本数据类型数据时,这个数据的值在初始化后将不能被改变。(变为常量)
* 当final修饰的是一个引用类型数据时,也就是修饰一个对象时,引用在初始化后将永远指向一个内存地址,不可修改;
* 但是该内存地址中保存的对象信息,是可以进行修改的。
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
final class Student {
private String sname;
private Integer age;
public void say1(String content){
System.out.println(content);
}
public static void say2(String content){
System.out.println(content);
}
public String say3(String content){
return content;
}
public static String say4(String content){
return content;
}
public static void dynamicSay(Function<String,String> func,String param){
String result=func.apply(param);
System.out.println(result);
}
public static void whoSay(Student student, String content){
//private可以给本类直接调用
System.out.println(student.sname + "-" + content);
}
public static String upper1(Integer num, String str2){
return num+"-"+str2.toUpperCase();
}
public String upper2(Integer num,String str2){
return num+"-"+str2.toUpperCase();
}
/**
* static主要有4中使用情况:成员变量、成员方法、代码块和内部类
* static关键字的基本作用就是:方便在没有创建对象的情况下来进行调用(方法/变量)。
*
* 常用static修饰成员变量为静态变量:
* 静态变量属于类,在内存中只有一个复制,只要静态变量所在的类被加载,
* 这个静态变量就会被分配空间,因此就可以被使用了。
* 对静态变量的引用有两种方式,分别是“类.静态变量"和”对象.静态变量"
* 实例变量属于对象,只有对象被创建后,实例变量才会被分配内存空间,
* 才能被使用,它在内存中存在多个复制,只有用“对象.实例变量”的方式来引用。
*
* 常用static修饰成员方法为静态方法:
* static方法是类的方法,不需要创建对象就可以被调用,而非static方法是对象的方法,
* 只有对象被创建出来后才可以被使用,static方法中不能使用this和super关键字,
* 不能直接调用非static方法和非static变量,只能直接访问所属类的静态成员变量和静态成员方法,
* 因为当static方法被调用时,这个类的对象可能还没被创建,即使已经被创建了,也无法确定调用哪个对象的方法。
*/
}