JDK8新特性
速度快,代码少(Lambda表达式)强大的Stream API 便于并行 最大化减少空指针异常
Nashorm引擎,允许在JVM上运行JS应用
并行流与串行流
Lambda表达式
概述:就是匿名函数
基本语法:(参数列表) —>{方法体}
@Test
public void test2(){
Comparator com = new Comparator() {
@Override
public int compare(Object o1, Object o2) {
return Integer.compare((Integer) o1,(Integer) o2);
}
};
System.out.println(com.compare(12, 24));
Comparator<Integer> com1 = ((o1, o2) -> Integer.compare(o1,o2));//Lambda表达式
System.out.println(com1.compare(30, 24));
System.out.println("----------------");
Comparator<Integer> com2 = Integer::compare;//方法引用
System.out.println(com2.compare(22, 22));
}
Lambda:
* 举例:(o1,o2) -> Integer.compare(o1,o2);
* 格式:
* ->:箭头操作符 左边:形参列表(接口中抽象方法得的形参列表)
* 右边:Lambda体,其实就是重写的抽象方法的方法体
* 使用情况:以下有六种情况
* 总结: 左边:参数类型可以省略。如果参数只有一个,其中的小括号可以省
* 右边:使用大括号,如果只有一个执行语句,则【{}和return】可以省略不写
* Lambda表达式本质:作为接口的实例【只有一个抽象方法】
* 接口的要求:函数式接口
//1 无参无返回值
@Test
public void test1(){
Runnable r2 = () -> {
System.out.println("Lambda");
System.out.println("无参无返回值");
};
r2.run();
}
//2 有参无返回值
@Test
public void test2(){
Consumer<String> con = new Consumer<String>() {
@Override
public void accept(String s) {
System.out.println("I like "+s);
}
};
con.accept("basketball");
Consumer<String> con2 = System.out::println;
con2.accept("124");
Consumer<String> con1 = (String s) -> { System.out.println("I like "+s);};
con1.accept("basketball");
}
//3 数据类型可以省略,因为可以由编译器推断出,称为“类型推断”
@Test
public void test3(){
Consumer<String> con1 = (s) -> { System.out.println("I like "+s);};
con1.accept("basketball");
}
//4 只有一个参数,参数的括号可以省略
@Test
public void test4(){
Consumer<String> con1 = s -> { System.out.println("I like "+s);};
con1.accept("basketball");
}
//5 有多个参数,多条执行语句,并且可以有返回值
@Test
public void test5(){
Comparator<Integer> com = (o1, o2) -> {
System.out.println(o1+" "+o2);
return Integer.compare(o1,o2);
};
System.out.println(com.compare(12, 24));
}
//6 只有一条执行语句,return与大括号有,都可以省略
@Test
public void test6(){
Comparator<Integer> com = (o1, o2) -> Integer.compare(o1,o2);
System.out.println(com.compare(12, 24));
}
Lambda表达式类型推断
函数式接口---》只包含一个抽象方法的接口
使用@FunctionInterface注解判断是否是函数时接口
函数式接口
Lambda之 方法引用
Stream
创建Stream
/**
* StreamAPI的使用
* //非关系型数据库就需要在java层面对数据进行删选 Radis MongDB
* Stream与Collection的区别:Collection是一种静态的内存数据结构 面向内存
* Stream是有关计算的 面向cpu 1不会存储数据 2不会改对象 3返回一个新对象 4操作是延迟的
* 1 创建Stream对象
* 2 中间操作
* 3 终止操作(只有调用终止操作,前面中间操作的才会顺序执行且不可逆)
*
* @author FuQingsong
* @create 2023-03-04-21:19
*/
public class StreamCreateTest {
@Test
public void test1(){
//1创建Stream对象(可以通过集合、数组)
List<Person> p = new ArrayList<>();
p.add(new Person(12,124));
p.add(new Person(11,14));
p.add(new Person(52,24));
p.add(new Person(12,1244));
p.add(new Person(1142,1244));
Stream<Person> stream = p.stream();// default Stream<E> stream():返回一个顺序流
Stream<Person> stream1 = p.parallelStream();//获取一个并行流
//2通过数组创建
int[] arr = new int[]{2,3,5,9,1};
IntStream stream2 = Arrays.stream(arr);// 注意基本数据类型数组的InStream
//3Stream.of() 它就是和集合打交道的
Stream<Integer> integerStream = Stream.of(1, 3, 4, 5, 6, 2);
//4创建无线流
// public static<T> Stream<T> iterate(final T seed, final UnaryOperator<T> f)
//遍历前十个偶数
Stream.iterate(0,t->t+2).limit(10).forEach(System.out::println);
// public static<T> Stream<T> generate(Supplier<T> s)
Stream.generate(Math::random).limit(10).forEach(System.out::println);
}
}
中间操作
public class StreamMIddleTest {
/*
筛选与切片
filter(Predicate p) 接收lambda,从流中排除某些元素
distinct() 筛选重复的元素,hashcode与equals【自定义的类需要重写】
limit(long maxSize) 截断流 使其中元素不超过给定的数量
skip(long n) 跳过n个元素,返回一个人扔掉了前n个元素的流,如果流中元素不足n个,则返回一个空流,与limit()互补
*/
@Test
public void test1(){
List<Person> p = new ArrayList<>();
p.add(new Person(12,124));
p.add(new Person(11,14));
p.add(new Person(52,24));
p.add(new Person(12,1244));
p.add(new Person(1142,1244));
Stream<Person> stream = p.stream();// default Stream<E> stream():返回一个顺序流
//filter(Predicate p) 接收lambda,从流中排除某些元素
//Predicate boolean test(T t):用来对指定数据类型数据进行判断的方法
// Predicate predicate = new Predicate() {
// @Override
// public boolean test(Object o) {
// if (o instanceof Person){
// Person p = (Person)o;
// return p.getAge()>30;
// }
// return true;
// }
// };
stream.filter(e -> e.getAge() > 30).forEach(System.out::println);
}
/*
映射 //自变量=====函数-===因变量
map(Function f) 接收一个函数作为参数将参数转换为其他形式或提取信息,孩函数会应用到每一个元素上,并将其映射成一个新的元素,
flatMap(Function f) 接收一个函数作为参数,将流中的每一个值都换成另一个流,然后把所有的流连接成一个流
mapToXxx(ToDoubleFunction f)【Double Int Long】 产生一个DoubleStream流
*/
@Test
public void test2(){
//Function R apply(T t) 放入一个形参返回一个值
List<String> list = Arrays.asList("aa", "bb", "cc", "dd");
Stream<String> stream1 = list.stream();
stream1.map(str->str.toUpperCase()).forEach(System.out::println);
List<Person> p = new ArrayList<>();
p.add(new Person(12,124));
p.add(new Person(11,14));
p.add(new Person(52,24));
p.add(new Person(12,1244));
p.add(new Person(1142,1244));
Stream<Person> stream = p.stream();// default Stream<E> stream():返回一个顺序流
//Function R apply(T t) 放入一个形参返回一个值
//打印年龄大于30的人
stream.map(e ->e.getAge()>30? e:null).forEach(System.out::println);
p.stream().map(e -> e.getAge()).filter(age -> age > 30).forEach(System.out::println);
System.out.println("=============");
Stream<Integer> agesStream = p.stream().map(Person::getAge);
agesStream.filter(age -> age > 30).forEach(System.out::println);
// flatMap(Function f) 接收一个函数作为参数,将流中的每一个值都换成另一个流,然后把所有的流连接成一个流//addAll
list.stream().map(StreamMIddleTest::getStream).forEach(e ->{
e.forEach(System.out::println);
});
list.stream().flatMap(StreamMIddleTest::getStream).forEach(System.out::println);
}
@Test
public void test3(){
ArrayList arr1 = new ArrayList();
arr1.add(1);
arr1.add(2);
arr1.add(3);
ArrayList arr2 = new ArrayList();
arr2.add(4);
arr2.add(5);
arr2.add(6);
arr1.add(arr2);
System.out.println(arr1);
}
public static Stream<Character> getStream(String str){
ArrayList<Character> characters = new ArrayList<>();
for(Character c : str.toCharArray()){
characters.add(c);
}
return characters.stream();
}
//排序
/*
sorted() 产生一个新流 按自然排序
sorted(Comparator com) 产生一个新流 按比较器顺序排序
*/
@Test
public void test4(){
List<Integer> list = Arrays.asList(3, 1, 33, 12);
list.stream().sorted().forEach(System.out::println);
Comparator<Integer> com = new Comparator<Integer>(){
@Override
public int compare(Integer o1, Integer o2) {
return -o1.compareTo(o2);
}
};
list.stream().sorted(com).forEach(System.out::println);
System.out.println("-----------------");
list.stream().sorted((o1, o2) -> -o1.compareTo(o2)).forEach(System.out::println);
}
}
终止操作
public class StreamFinalTest {
/*
//1 匹配与查找
allMatch(Predicate p) 检查是否匹配所有的元素
anyMatch(Predicate p) 检查是否至少匹配一个元素
noneMatch(Predicate p) 检查是否没有匹配元素
findFirst 返回第一个元素
findAny 获取任意一个元素
count 返回流中元素的个数
max(Comparator com) 返回流中最大的值
min(Comparator com) 返回流中最小的值
forEach(Consumer c) 内部迭代
*/
@Test
public void test1(){
ArrayList<Person> p = new ArrayList<>();
p.add(new Person(12,14));
p.add(new Person(11,14));
p.add(new Person(52,24));
p.add(new Person(12,1244));
p.add(new Person(1142,1244));
p.forEach(System.out::println);//集合迭代0
//是否所有的年龄大于18岁
System.out.println(p.stream().allMatch(e -> e.getAge() > 18));// allMatch(Predicate p) 检查是否匹配所有的元素
//是否存在年龄大于30岁
System.out.println(p.stream().anyMatch(e -> e.getAge() > 18));//anyMatch(Predicate p) 检查是否至少匹配一个元素
//是否存在id=14的人(false 表示存在 true 表示没有这个人)
System.out.println(p.stream().noneMatch(e -> e.getId() == 14));//noneMatch(Predicate p) 检查是否没有匹配元素
//返回第一个员工
System.out.println(p.stream().findFirst()); //findFirst 返回第一个元素
//所有的年龄大于18岁的个数
System.out.println(p.stream().map(Person::getAge).filter(age -> age > 18).count());//count 返回流中元素的个数
//返回年龄最大
System.out.println(p.stream().max((o1, o2) -> o1.getAge() - o2.getAge()));// max(Comparator com) 返回流中最大的值
}
//2 规约
/* 初始值
reduce(T identity, BinaryOperator b) 可以将流中元素结合起来,得到一个值,返回T
reduce(BinaryOperator b) 可以将流中元素反复结合起来,得到一个值,返回Optional<T>
*/
@Test
public void test2(){
//1-10自然数的和
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
Integer reduce = list.stream().reduce(0, Integer::sum);
System.out.println(reduce);
System.out.println(list.stream().reduce(Integer::sum));//Optional[55]
}
//3 收集
/*
collect(Collect c) 将流转换为其他方式,接收一个Collector接口的实现,用于给Stream中的元素做汇总的方法
*/
@Test
public void test3(){
ArrayList<Person> p = new ArrayList<>();
p.add(new Person(12,14));
p.add(new Person(11,14));
p.add(new Person(52,24));
p.add(new Person(12,1244));
p.add(new Person(1142,1244));
List<Person> collect = p.stream().filter(e -> e.getAge() > 18).collect(Collectors.toList());//toSet()
System.out.println(collect);
}
}
Optional类
/**
* Optional<T> 避免空指针 也是一种容器,所承下的数有限
* 常用的方法:ofNullable orElse 两个方法
* 从Optional拿数据使用 get 注意是否为空(null) isPresent()是否为空
* @author FuQingsong
* @create 2023-03-06-18:46
*/
public class OptionalTest {
@Test
public void test1(){
//创建
Girl girl = new Girl();
Optional<Girl> o1 = Optional.of(new Girl());//创建实例 参数不能为空
girl = null;
Optional<Girl> o2 = Optional.ofNullable(girl);//参数可以是null
//orElse(T t1)如果单前的Optional的内部封装的t是非空的,则返回内部的t,如果内部t是空的,返回orElse方法中的参数t1
Optional<Object> empty = Optional.empty();//创建一个空的Optional实例
}
// @Test
// public void test2(){
// //错误的示范;---->空指针异常
// Boy boy = new Boy();
// String name = getName(boy);
// System.out.println(name);
// }
public String getName(Boy boy){
//会出现空指针
return boy.getGirl().getName();
}
//优化getName() 需要一层一层的进行的判断
public String getGirlName(Boy boy){
if (boy != null){
Girl girl = boy.getGirl();
if (girl != null) return girl.getName();
}
return null;
}
//使用Optional类优化的getgirlName的方法
public String getMMName(Boy boy){
Optional<Boy> boy1 = Optional.ofNullable(boy);
Boy boy2 = boy1.orElse(new Boy(new Girl("qw", 12)));
Girl girl = boy2.getGirl();
Optional<Girl> girl1 = Optional.ofNullable(girl);
Girl girl2 = girl1.orElse(new Girl("qr", 2));
return girl2.getName();
}
}