Java8新特性
接口中默认方法修饰为普通方法
在jdk8之前,interface之中可以定义变量和方法,变量必须是public、static、final的,方法必须是public、abstract的,由于这些修饰符都是默认的。
接口定义方法:public 抽象方法 需要子类实现
接口定义变量:public、static、final
在JDK 1.8开始 支持使用static和default 修饰 可以写方法体,不需要子类重写。
方法:
普通方法 可以有方法体
抽象方法 没有方法体需要子类实现 重写。
代码案例
/**
* ClassName:Jdk8Interface
* Package:com.yt
* Description:
*
* @date:2021/8/2 15:51
* @author:yt
*/
public interface Jdk8Interface {
/**
* 抽象方法 需要子类实现
* 默认类型:public、abstract
*/
void addOrder();
/**
* default方法
*/
default void defaultGet() {
System.out.println("我是default方法");
}
/**
* static方法
*/
static void staticGet() {
System.out.println("我是static方法");
}
}
/**
* ClassName:Jdk8InterfaceImpl
* Package:com.yt
* Description:
*
* @date:2021/8/2 15:56
* @author:yt
*/
public class Jdk8InterfaceImpl implements Jdk8Interface{
/**
* 默认的情况下必须重写接口中抽象方法 默认和静态方法是不需要必须重写
*/
@Override
public void addOrder() {
System.out.println("add");
}
}
Lambda表达式
什么是Lambda表达式
LAMBADA 好处: 简化我们匿名内部类的调用。
Lambda+方法引入 代码变得更加精简。
Lambda 表达式(lambda expression)是一个匿名函数,简化我们调用匿名函数的过程。
百度百科介绍:
https://baike.baidu.com/item/Lambda%E8%A1%A8%E8%BE%BE%E5%BC%8F/4585794?fr=aladdin
为什么要使用Lambda表达式
可以非常简洁的形式调用我们的匿名函数接口。
public static void main(String[] args) {
// 1.使用new的实现类的形式调用接口
OrderService orderSerivce1 = new OrderSerivceImpl();
orderSerivce1.addOrder();
// 2.使用匿名内部接口调用
new OrderService() {
@Override
public void addOrder() {
System.out.println("使用匿名内部类的形式调用接口");
}
}.addOrder();
// 3.使用lambda调用接口
OrderService orderSerivce2= ()-> System.out.println("使用lambda调用接口");
orderSerivce2.addOrder();
}
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修饰为函数接口
函数接口定义
-
在接口中只能有一个抽象方法
-
@FunctionalInterface 标记为该接口为函数接口
-
可以通过default 修饰为普通方法
-
可以定义object类中的方法
@FunctionalInterface
public interface MyFunctionalInterface {
void get();
default void defaultAdd() {
System.out.println("我是默认的方法");
}
/**
* object父类中的方法可以在 函数接口中重写
*
* @return
*/
@Override
String toString();
}
Java系统内置那些函数接口
消费型接口:
Conusmer<T>
void accept(T t);
BiConusmer<T,U>
void accept(T t,U u);//增加一种入参类型
供给型接口
Supplier<T>
void get();
函数型接口
Function<T ,R>
R apply(T t);
UnaryOperator<T>
T apply(T t);//入参与返回值类型一致
BiFunction <T ,U,R>
R apply(T t,U u);//增加一个参数类型
BinaryOperator<T>
T apply(T t1,T t2);//l两个相同类型入参与同类型返回值
ToIntFunction<T>//限定返回int
ToLongFunction<T>//限定返回long
ToDoubleFunction<T>//限定返回double
IntFunction<R>//限定入参int,返回泛型R
LongFunction<R>//限定入参long,返回泛型R
DoubleFunction<R>//限定入参double,返回泛型R
断言型接口
Predicate<T>
boolean test(T t);
Lambda基础语法
()//参数列表
-> //分隔
{} //方法体
(a,b)->{
}
无参方法调用
带参数方法调用
(函数接口的参数列表 不需要写类型 需要定义参数名称)->{方法体}
()//函数方法参数列表
->//分隔
{}//方法体
(a,b)->{
Sout(a,b)
}
Lambda语法:
():参数列表
->分隔
{}:方法体
()->{}
无参方法调用
@FunctionalInterface
public interface AcanthopanaxInterface {
void get();
}
((AcanthopanaxInterface) () -> System.out.println("get")).get();
带参数和返回值
@FunctionalInterface
public interface YouShenInterface {
String get(int i, int j);
}
@Test
public void test06() {
// 1.使用匿名内部类调用有参数函数方法
String result = new YouShenInterface() {
@Override
public String get(int i, int j) {
return i + "-" + j;
}
}.get(1, 1);
System.out.println(result);
}
@Test
public void test07() {
//2.使用lambda 调用有参数函数方法
String result = ((YouShenInterface) (i, j) -> i + "-" + j).get(1, 1);
System.out.println(result);
}
精简语法
@Test
public void test08() {
AcanthopanaxInterface acanthopanaxInterface = () -> System.out.println("我是方法");
acanthopanaxInterface.get();
// 精简代码 // 使用Lambda 方法体中只有一条语句的情况下,在这时候我们不需要写{} 也可以不需要写return
((AcanthopanaxInterface) () -> System.out.println("我是方法")).get();
YouShenInterface youShenInterface = (i, j) -> {
return i + "-" + j;
};
YouShenInterface youShenInterface2 = (i, j) -> i + "-" + j;
String s = ((YouShenInterface) (i, j) -> i + "-" + j).get(1, 2);
System.out.println(s);
}
方法引入
什么是方法引入
方法引入:需要结合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表达式中直接引入的方法。
必须遵循规范:引入的方法参数列表返回类型必须要和函数接口参数列表、返回类型保持一致。
静态方法引入
@FunctionalInterface
public interface MessageInterface {
void get(Integer a);
}
@Test
public void test12() {
// 1.最原生匿名内部类调用方式
MessageInterface messageInterface = new MessageInterface() {
@Override
public void get(Integer a) {
System.out.println("geta:" + a);
}
};
messageInterface.get(1);
// 在Lambda表达式中方法体直接引入方法
MessageInterface messageInterface2 = (a) -> MyTest.staticGet(a);
// // 方法引入 --实际上就是我们 Lambda表达式中方法体直接引入方法---
messageInterface2.get(2);
// // 方法引入写法
MessageInterface messageInterface3 = MyTest::staticGet;
messageInterface3.get(10);
/**
* MyTest::staticGet为何能够等于
* (a) -> MyTest.staticGet(a);
*/
}
public static void staticGet(Integer a) {
System.out.println("staticGet,a:" + a);
}
对象方法引入
@FunctionalInterface
public interface YtService {
String get(Test test);
}
public class Test {
public static void main(String[] args) {
// 1.使用匿名内部类的形式
YtService ytService = new YtService() {
@Override
public String get(Test test) {
return test.objGet();
}
};
System.out.println(ytService.get(new Test()));
// 2.Lambda
YtService ytService1 = (test -> test.objGet());
System.out.println(ytService1.get(new Test()));
// 3.方法引入 在这时候我们函数接口 第一个参数传递test 返回调用test.objGet方法
YtService ytService2 = Test::objGet;
System.out.println(ytService2.get(new Test()));
//Test::objGet;----- (test) -> test.objGet();
// R apply(T t); T apply方法传递的参数类型 : R apply 方法返回的类型
// 需要将string类型字符串获取长度
// Function<String, Integer> strFunction = (str) -> {
// return str.length();
// };
Function<String, Integer> strFunction = String::length;
System.out.println(strFunction.apply("yt"));
}
public String objGet() {
return "yt";
}
}
实例方法引入
@FunctionalInterface
public interface MessageInterface {
void get(Integer a);
}
@Test
public void test13(){
MyTest myTest = new MyTest();
MessageInterface2 messageInterface= ()->"yt666";
System.out.println(messageInterface.getMessage());
MessageInterface2 messageInterface3= myTest::objGet;
System.out.println(messageInterface3.getMessage());
}
public String objGet() {
return "yt666";
}
构造函数引入
@Data
@AllArgsConstructor
@NoArgsConstructor
public class MessageEntity {
private String messageId;
private String messageName;
}
@Test
public void test14() {
MessageInterface3 messageInterface3 = () -> {
return new MessageEntity();
};
/**
* 构造函数引入 遵循规范:函数接口返回类型::new
*/
MessageInterface3 messageInterface4 = MessageEntity::new;
System.out.println(messageInterface4.getMessage());
}
Lambda实战案例
Foreach
ArrayList<String> strings = new ArrayList<>();
strings.add("yt");
strings.add("ytt");
strings.add("yttt");
strings.forEach(s -> System.out.println(s));
Lambda集合排序
@Data
@AllArgsConstructor
@NoArgsConstructor
public class UserEntity {
private String userName;
private int age;
}
@Test
public void test10() {
List<UserEntity> userEntities = new ArrayList<>();
userEntities.add(new UserEntity("yt", 12));
userEntities.add(new UserEntity("ls", 19));
userEntities.add(new UserEntity("zs", 18));
userEntities.sort((o1, o2) -> o1.getAge() - o2.getAge());
userEntities.forEach(t -> System.out.println(t));
}
线程调用
new Thread(() -> System.out.println("我是子线程")).start();
java 8 stream流
什么是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 mayikt where userName =‘mayikt’
Order by age limt(0,2)
Stream创建方式
parallelStream为并行流采用多线程执行
Stream采用单线程执行
parallelStream效率比Stream要高。
ArrayList<UserEntity> userEntities = new ArrayList<>();
userEntities.add(new UserEntity("mayikt", 20));
userEntities.add(new UserEntity("meite", 28));
userEntities.add(new UserEntity("zhangsan", 35));
userEntities.add(new UserEntity("xiaowei", 16));
userEntities.add(new UserEntity("xiaowei", 16));
userEntities.stream();
userEntities.parallelStream();
Stream将list转换为Set
@Test
public void test01() {
ArrayList<UserEntity> userEntities = new ArrayList<>();
userEntities.add(new UserEntity("yt", 20));
userEntities.add(new UserEntity("ytt", 28));
userEntities.add(new UserEntity("zs", 35));
userEntities.add(new UserEntity("xw", 16));
userEntities.add(new UserEntity("xw", 16));
/**
* user 对象属性值都是相等的 但是new 两个对象 这两个对象的 内存地址 是不一样的
*/
/**
* 创建stream方式两种
* 1.串行流stream() 单线程
* 2.并行流parallelStream() 多线程
* 并行流parallelStream 比串行流stream()效率要高的
*/
Stream<UserEntity> stream = userEntities.stream();
// 转换成set集合
Set<UserEntity> setUser = stream.collect(Collectors.toSet());
setUser.forEach(userEntity -> System.out.println(userEntity));
}
Stream将list转换为Map
@Test
public void test02() {
ArrayList<UserEntity> userEntities = new ArrayList<>();
userEntities.add(new UserEntity("yt", 20));
userEntities.add(new UserEntity("ytt", 28));
userEntities.add(new UserEntity("zs", 35));
userEntities.add(new UserEntity("xw", 16));
/**
* user 对象属性值都是相等的 但是new 两个对象 这两个对象的 内存地址 是不一样的
*/
/**
* 创建stream方式两种
* 1.串行流stream() 单线程
* 2.并行流parallelStream() 多线程
* 并行流parallelStream 比串行流stream()效率要高的
*/
Stream<UserEntity> stream = userEntities.stream();
Map<String, UserEntity> collect = stream.collect(Collectors.toMap(userEntity -> userEntity.getUserName(), userEntity -> userEntity));
collect.forEach((s, userEntity) -> System.out.println(s + "," + userEntity));
}
Stream将Reduce 求和
@Test
public void test03() {
Stream<Integer> integerStream = Stream.of(10, 50, 30, 10);
System.out.println(integerStream.reduce((integer, integer2) -> integer + integer2).get());
}
StreamMax和Min
@Test
public void test04() {
ArrayList<UserEntity> userEntities = new ArrayList<>();
userEntities.add(new UserEntity("mayikt", 20));
userEntities.add(new UserEntity("meite", 28));
userEntities.add(new UserEntity("zhangsan", 35));
userEntities.add(new UserEntity("liusi", 21));
userEntities.add(new UserEntity("wangmazi", 19));
userEntities.add(new UserEntity("xiaoke", 19));
userEntities.add(new UserEntity("xiaoan", 21));
Stream<UserEntity> stream = userEntities.stream();
Optional<UserEntity> max = stream.max((o1, o2) -> o1.getAge() - o2.getAge());
System.out.println(max);
Optional<UserEntity> min = stream.min((o1, o2) -> o1.getAge() - o2.getAge());
System.out.println(min);
}
StreamMatch 匹配
anyMatch表示,判断的条件里,任意一个元素成功,返回true
allMatch表示,判断条件里的元素,所有的都是,返回true
noneMatch跟allMatch相反,判断条件里的元素,所有的都不是,返回true
@Test
public void test05() {
ArrayList<UserEntity> userEntities = new ArrayList<>();
userEntities.add(new UserEntity("mayikt", 20));
userEntities.add(new UserEntity("meite", 28));
userEntities.add(new UserEntity("zhangsan", 35));
userEntities.add(new UserEntity("liusi", 21));
userEntities.add(new UserEntity("wangmazi", 19));
userEntities.add(new UserEntity("xiaoke", 19));
userEntities.add(new UserEntity("xiaoan", 21));
Stream<UserEntity> stream = userEntities.stream();
boolean b = stream.allMatch(userEntity -> "mayikt".equals(userEntity.getUserName()));
System.out.println(b);
}
StreamFor循环
@Test
public void test05() {
ArrayList<UserEntity> userEntities = new ArrayList<>();
userEntities.add(new UserEntity("mayikt", 20));
userEntities.add(new UserEntity("meite", 28));
userEntities.add(new UserEntity("zhangsan", 35));
userEntities.add(new UserEntity("liusi", 21));
userEntities.add(new UserEntity("wangmazi", 19));
userEntities.add(new UserEntity("xiaoke", 19));
userEntities.add(new UserEntity("xiaoan", 21));
Stream<UserEntity> stream = userEntities.stream();
stream.forEach((userEntity -> System.out.println(userEntity.toString())));
}
Stream过滤器
@Test
public void test06() {
ArrayList<UserEntity> userEntities = new ArrayList<>();
userEntities.add(new UserEntity("mayikt", 20));
userEntities.add(new UserEntity("meite", 28));
userEntities.add(new UserEntity("zhangsan", 35));
userEntities.add(new UserEntity("liusi", 21));
userEntities.add(new UserEntity("wangmazi", 19));
userEntities.add(new UserEntity("xiaoke", 19));
userEntities.add(new UserEntity("xiaoan", 21));
Stream<UserEntity> stream = userEntities.stream();
stream.filter(userEntity -> "mayikt".equals(userEntity.getUserName()) && userEntity.getAge() > 18).forEach(userEntity -> System.out.println(userEntity));
}
Stream排序 sorted
@Test
public void test08() {
ArrayList<UserEntity> userEntities = new ArrayList<>();
userEntities.add(new UserEntity("mayikt", 20));
userEntities.add(new UserEntity("meite", 28));
userEntities.add(new UserEntity("zhangsan", 35));
userEntities.add(new UserEntity("liusi", 21));
userEntities.add(new UserEntity("wangmazi", 19));
userEntities.add(new UserEntity("xiaoke", 19));
userEntities.add(new UserEntity("xiaoan", 21));
Stream<UserEntity> stream = userEntities.stream();
stream.sorted((o1, o2) -> o2.getAge() - o1.getAge()).forEach(userEntity -> System.out.println(userEntity));
}
Stream limit和skip
Limit 从头开始获取
Skip 就是跳过
@Test
public void test07() {
ArrayList<UserEntity> userEntities = new ArrayList<>();
userEntities.add(new UserEntity("mayikt", 20));
userEntities.add(new UserEntity("meite", 28));
userEntities.add(new UserEntity("zhangsan", 35));
userEntities.add(new UserEntity("liusi", 21));
userEntities.add(new UserEntity("wangmazi", 19));
userEntities.add(new UserEntity("xiaoke", 19));
userEntities.add(new UserEntity("xiaoan", 21));
Stream<UserEntity> stream = userEntities.stream();
// mysql limit(0,2) stream分页 (开始skip()) 结束:limit
//stream.skip((n-1)*m).limit(m)==mysql的limit (n-1)*m,m
stream.skip(2).limit(3).forEach(userEntity -> System.out.println(userEntity));
}
Stream 综合案例
@Test
public void test09() {
ArrayList<UserEntity> userEntities = new ArrayList<>();
userEntities.add(new UserEntity("mayikt", 20));
userEntities.add(new UserEntity("meite", 28));
userEntities.add(new UserEntity("zhangsan", 35));
userEntities.add(new UserEntity("xiaowei", 16));
userEntities.add(new UserEntity("mayikt_list", 109));
userEntities.add(new UserEntity("mayikt_zhangsan", 110));
userEntities.add(new UserEntity("lisi", 109));
userEntities.add(new UserEntity("mayikt", 66));
userEntities.add(new UserEntity("mayikt", 78));
userEntities.add(new UserEntity("mayikt", 32));
//要求:对数据流的数据实现降序排列、且名称为mayikt 获取后两位数据
Stream<UserEntity> stream = userEntities.stream();
stream.sorted((o1, o2) -> o2.getAge() - o1.getAge()).filter(userEntity -> "mayikt".equals(userEntity.getUserName())).skip(2)
.forEach((userEntity -> System.out.println(userEntity)));
}
并行流与串行流区别
串行流:单线程的方式操作; 数据量比较少的时候。
并行流:多线程方式操作;数据量比较大的时候,原理:
Fork join 将一个大的任务拆分n多个小的子任务并行执行,
最后在统计结果,有可能会非常消耗cpu的资源,确实可以
提高效率。
注意:数据量比较少的情况下,不要使用并行流。
@Test
public void test10() {
Instant start = Instant.now();
long sum = 0;
for (long i = 0; i <= 50000000000L; i++) {
sum += i;
}
System.out.println(sum);
Instant end = Instant.now();
// 单线程:五百亿求和花费的时间为: 13.243s
System.out.println("五百亿求和花费的时间为: " + Duration.between(start, end).toMillis()*1.0/1000+"s");
}
@Test
public void test11() {
Instant start = Instant.now();
LongStream longStream = LongStream.rangeClosed(0, 50000000000L);
// 使用并行流 计算 五百亿求和耗费的时间为: 7324 7850 7
OptionalLong result = longStream.parallel().reduce((left, right) -> left + right);
//使用多线程 处理 大的任务拆分成n多小的任务 在计算 在将结果合并 fork join框架
System.out.println(result.getAsLong());
Instant end = Instant.now();
System.out.println("五百亿求和耗费的时间为: " + Duration.between(start, end).toMillis()*1.0/1000+"s");
}
JDK8Optional
Optional 类是一个可以为null的容器对象。如果值存在则isPresent()方法会返回true,调用get()方法会返回该对象。
Optional 是个容器:它可以保存类型T的值,或者仅仅保存null。Optional提供很多有用的方法,这样我们就不用显式进行空值检测。
Optional 类的引入很好的解决空指针异常。
判断参数是否为空
ofNullable(可以传递一个空对象)
Of(不可以传递空对象)
@Test
public void test01() {
String username = null;
/*
ofNullable 可以允许传递一个空值对象
of 不允许传递一个空值对象
*/
Optional<String> optional = Optional.ofNullable(username);
// Optional<String> optional = Optional.of(userName);
// System.out.println(optional.get());
//false 返回false 则表示 值是为空 true 值不为空
System.out.println(optional.isPresent());
}
isPresent 返回 true 不为空, isPresent 返回 false 为空。
参数为空可以设定默认值
@Test
public void test02() {
String username = null;
System.out.println(Optional.ofNullable(username).orElse("yt"));
}
参数实现过滤
@Test
public void test03() {
String username = "yt";
System.out.println(Optional.ofNullable(username).filter(s -> "yt".equals(s)).isPresent());
}
与Lambda表达式结合使用,优化代码
优化方案1
@Test
public void test04() {
// 优化前
String username = "yt";
if (username != null) {
System.out.println(username);
}
//优化后
Optional<String> username2 = Optional.ofNullable(username);
// // 当value 为空时,则不会调用
// username2.ifPresent(s -> System.out.println(s));
//username不为空的情况下 直接调用accept 打印值 username==null的情况下 就不会执行accept
username2.ifPresent(System.out::print);
}
优化方案2
public class MyTest {
private static OrderEntity orderEntity;
@Test
public void test05(){
System.out.println(MyTest.getOrder());
System.out.println(MyTest.orderEntity);
}
public static OrderEntity getOrder() {
// 优化前
// if (orderEntity == null) {
// orderEntity = createOrder();
// }
/**
* orElseGet()---写函数的接口的形式 赋默认值
* orElse()----直接传递默认值
*/
// return orderEntity;
// return Optional.ofNullable(orderEntity).orElse(createOrder());
return Optional.ofNullable(orderEntity).orElseGet(MyTest::orElseGet);
}
private static OrderEntity createOrder() {
return new OrderEntity("123456", "yt","");
}
public static OrderEntity orElseGet() {
orderEntity = createOrder();
return orderEntity;
}
}
优化方案3
map中获取的返回值自动被Optional包装,即返回值 -> Optional<返回值>
flatMap中返回值保持不变,但必须是Optional类型,即Optional<返回值> -> Optional<返回值>
@Test
public void test06(){
String orderName = MyTest.getOrderName();
System.out.println(orderName);
}
public static String getOrderName() {
// 优化前写法:
OrderEntity order = new OrderEntity("123456", "Yt","");
// if (order != null) {
// String orderName = order.getOrderName();
// if (orderName != null) {
// return orderName.toLowerCase();
// }
// }
//获取我们对象中 orderNameOptional
// Optional<OrderEntity> orderOptional = Optional.ofNullable(order);
// Optional<String> orderNameOptional = orderOptional.map(orderEntity -> orderEntity.getOrderName());
// Optional<String> toLowerCase = orderNameOptional.map(name ->
// name.toLowerCase());
return Optional.ofNullable(order).map(orderEntity -> orderEntity.getOrderName()).map(orderName -> orderName.toLowerCase()).orElse(null);
}