一直在使用JAVA8,但是没有系统的学习过JAVA8,也是一知半解,入手JAVA8实战,系统的了解和学习JAVA8的内容。
书籍:《JAVA8实战》
视频:https://www.bilibili.com/video/BV1VW41127sh?spm_id_from=333.337.search-card.all.click&vd_source=fce799ae483f16799f55fcb9708668ff
(1)多核处理大型数据集
(2)函数式编程更适应新的体系架构
因此,核心特性为:Lambda、流、默认方法
下面的代码是获取当前目录隐藏文件和目录的方法,可以看到JAVA8的实现,(1)代码量少,(2)内存少(不再使用内部类,占用内存会变少)
File[] hiddenFiles = new File("./").listFiles(new FileFilter() {
@Override
public boolean accept(File pathname) {
return pathname.isHidden();
}
});
File[] hiddenFilesJav8 = new File("./").listFiles(File::isHidden);
JAVA8引入了::语法,即把这个值作为函数,那么将方法传递给方法又是如何做到的呢?肯定是有一个东东是可以接收方法的,JAVA8使用Predictate和Function实现,例如下面的代码,其中Predicate就是谓词方式,即给定一个T,返回一个boolean值,true或者false,JAVA8也会允许你写Function
package com.example.demo.guava;
import lombok.Data;
import org.apache.commons.lang3.StringUtils;
import java.util.ArrayList;
import java.util.List;
/**
* @author Administrator
* @since 2022/9/6 22:39
*/
@Data
class Apple {
private String green;
private Integer weight;
public static boolean isGreenApple(Apple apple) {
return StringUtils.equals("green", apple.getGreen());
}
public static boolean isHeavyApple(Apple apple) {
return 50 < apple.getWeight();
}
}
public class FunctionalTest {
public interface Predicate<T> {
boolean test(T t);
}
static List<Apple> filterApples(List<Apple> inventory, Predicate<Apple> p) {
List<Apple> result = new ArrayList<>();
for (Apple apple : inventory) {
if (p.test(apple)) {
result.add(apple);
}
}
return result;
}
public static void main(String[] args) {
List<Apple> inventory = new ArrayList<>();
filterApples(inventory, Apple::isGreenApple);
filterApples(inventory, Apple::isHeavyApple);
}
}
那么,第一个案例又是使用的哪个呢?
File的listFiles()参数时FileFilter,是一个函数式接口,入参是File,返回的是一个boolean,正好File的isHidden入参是File,返回是boolean,实现了此方法的调用。
上面的方法虽然实现了函数的传递,但是仍然需要定义函数,那有没有简便的写法呢,即lambda的方法了(匿名函数)。
filterApples(inventory, apple -> StringUtils.equals("green", apple.getGreen()));
filterApples(inventory, apple -> 50 < apple.getWeight());
lambda的语法糖方法引用 ::
都哪些方法可以使用方法引用呢:
(1)静态方法
List<String> tmp = Arrays.asList("1", "3", "5");
tmp.forEach(Integer::parseInt);;
(2)实例方法String::length
(3)无参构造函数 Apple::new
1.Predictate函数式接口
给定一个参数,方法是返回一个boolean,即当方法使用的是Predicate参数时,即可以使用Predicate的函数式接口了。
可以使用举例:
ArrayList的方法:
Predict有很多其它的方法,比如and、or、not、
Predicate predicate1 = o1->StringUtils.equals("李天一","李天二");
Predicate predicate2 = o1->StringUtils.equals("李天一","李天一");
aservice.sout(predicate1.or(predicate2)); // 官二代
自定义方法,支持Predicate的函数式接口,直接参数设置成Predicate即可。
@Data
@AllArgsConstructor
public class AService {
private String name;
public void sout(Predicate predicate) {
if (predicate.test(name)) {
System.out.println("官二代");
} else {
System.out.println("寒门");
;
}
}
}
单测代码:
private AService aservice = new AService("李天一");
@Test
public void testSout() throws Exception {
aservice.sout(o1-> StringUtils.equals(aservice.getName(),"李天一"));
}
2.Consumer接口
Consumer接口是消费型接口,对一个给定对象直接处理。
Comsumer还有一个接口,是andThen(),即先执行一个消费方法,再执行一个消费方法
Consumer consumer1 = o1->System.out.println("李天一");
Consumer consumer2 = o1->System.out.println("李天二");
aservice.compare(consumer1.andThen(consumer2)); // 李天一 李天二
自定义Consumer
public void compare(Consumer consumer){
consumer.accept(name);
}
单测
@Test
public void testConsumer() throws Exception{
aservice.compare(o1-> System.out.println(aservice.getName()));
}
最常使用的是Collection接口的foreach函数
3.Function接口
Function接口是给定两个参数,返回一个参数的方法。同样有一些组合Function,compose(组合) 、andThen(然后)、identify()
抄袭一个大神的代码,compose是先执行的,andThen是后执行的
Function<Integer, Integer> times2 = i -> i*2;
Function<Integer, Integer> squared = i -> i*i;
System.out.println(times2.apply(4));
System.out.println(squared.apply(4));
//32 先4×4然后16×2,先执行apply(4),在times2的apply(16),先执行参数,再执行调用者。
System.out.println(times2.compose(squared).apply(4));
//64 先4×2,然后8×8,先执行times2的函数,在执行squared的函数。
System.out.println(times2.andThen(squared).apply(4));
//16
System.out.println(Function.identity().compose(squared).apply(4));
函数式接口就是只有一个函数的接口,可以添加@FunctionalInterface对于编译器编译提示。
public interface OrderService {
void saveOrder();
}
或者
@FunctionalInterface
public interface OrderService {
void saveOrder();
}
持续优化中
总结
整体梳理了一下JAVA8 Lamdba的使用和函数式接口、自定义函数式接口,对设计模式的优化需要持续学习。