文章目录
Java 8 新特性
一、Lambda表达式
1.1 简介
Lambda是一个匿名函数,可将该表达式理解为一段可传递的代码。可以使代码更简洁灵活,使代码风格更加紧凑,提升Java语言的表达能力。
/**
* @return void
* @Param
* @Date 22:04 2021/7/26
* @Description: 匿名内部类
**/
@Test
public void test() {
Comparator<Integer> comparator = new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return Integer.compare(o1, o2);
}
};
TreeSet<Integer> treeSet = new TreeSet<>(comparator);
}
/**
* @return void
* @Param
* @Date 22:06 2021/7/26
* @Description: Lambda表达式
**/
@Test
public void test(){
Comparator<Integer> com=(a, b) -> Integer.compare(a, b);
TreeSet<Integer> treeSet = new TreeSet<>(com);
}
1.2 语法
-
Java8引入新的操作符“->”,该操作符将Lambda表达式分为两部分
- 左侧:Lambda表达式的参数列表
- 右侧:Lambda表达式需要进行的功能
-
语法格式一:无参数 无返回值
()-> System.out.println();
-
语法格式二:一个参数 无返回值
(z)-> System.out.println(z);//一个参数时小括号可省略 //Lambda体中若只有一条语句则大括号和return都可省略
-
语法格式三:多个参数 有返回值 Lambda体中有多条语句
Comparator<Integer> com = (x, y) -> { System.out.println("Lambda!"); return Integer.compare(x, y); };
-
语法格式四:Lambda表达式中参数列表的数据类型可以省略不写,因为JVM可以根据上下文推断出数据类型
@Test public void test() { Runnable r = () -> System.out.println("run()"); r.run(); Consumer<String> con = x -> System.out.println(x); con.accept("Hello!"); Comparator<Integer> com = (x, y) -> { System.out.println("Lambda!"); return Integer.compare(x, y); }; }
注意:Lambda表达式需要“函数式接口的支持”
1.3 函数式接口
- 接口中只有一个抽象方法,则称为函数式接口
- @FunctionalInterface注解修饰的接口必须是函数式接口
1.4 四大内置接口
-
Consumer接口:消费型接口
@Test public void test() { happy(100, a -> System.out.println("消费" + a + "元")); } public void happy(double money, Consumer<Double> con) { //accept()方法 con.accept(money); }
-
Supplier接口:供给型接口
@Test public void test() { List<Integer> numList = getNumList(10, () -> (int) (Math.random() * 100)); for (Integer integer : numList) { System.out.println(integer); } } public List<Integer> getNumList(int num, Supplier<Integer> sup) { ArrayList<Integer> list = new ArrayList<>(); for (int i = 0; i < num; i++) { //get()方法 Integer n = sup.get(); list.add(n); } return list; }
-
Function<T,R>接口:函数型接口
@Test public void test() { String str = strHandler(" Hello ", String::trim); System.out.println(str);//Hello } private String strHandler(String str, Function<String, String> fun) { //apply()方法 return fun.apply(str); }
-
Predicate接口:断言型接口
@Test public void test() { List<String> list = Arrays.asList("hello", "Lambda", "ok", "word"); List<String> o = filterStr(list, s -> s.contains("o")); for (String s : o) { System.out.println(s); } } private List<String> filterStr(List<String> list, Predicate<String> pre) { ArrayList<String> strings = new ArrayList<>(); for (String s : list) { //test()方法 if (pre.test(s)) { strings.add(s); } } return strings; }
1.5 方法引用
若Lambda体中的内容有方法已经实现了,我们可以使用“方法引用”。即方法应用是Lambda表达式的另外一种表现形式。主要有三种语法格式如下:
-
对象::实例方法名
@Test public void test(){ PrintStream print = System.out; Consumer<String> con=x->print.println(x); Consumer<String> cons= print::println; Consumer<String> consu= System.out::println; //println和accept方法的参数列表和返回值相同 consu.accept("Hello"); }
-
类::静态方法名
@Test public void test(){ Comparator<Integer> com=(x,y)->Integer.compare(x,y); Comparator<Integer> com1=Integer::compare; int compare = com1.compare(2, 1); System.out.println(compare); }
-
类::实例方法名
-
注意:
- Lambda体中调用方法的参数列表与返回值类型要与函数式接口中抽象方法的函数列表和返回值类型保持一致
二、StreamAPI
2.1 概述
该API是Java 8中处理集合的关键抽象概念。它可以用来操作集合,可以对集合做一些复杂的操作例如过滤、查找、映射数据等。
实际开发中,项目中使用的数据源来自于MySQL、Oracle等。但是现在的数据源也包括MongDB、Radis等一些非关系型数据库,而这些NoSQL的数据就需要Java层面对这些数据进行过滤,所以就会用到StreamAPI。
- Stream不会存储元素
- Stream不会改变源对象
- Stream的操作时延时的,即他们会等到需要结果的时候才执行。
2.2 步骤
- 创建Stream
- 从数据源获(集合、数组等)取一个Stream流
- 中间操作
- 中间操作链,对数据进行处理(过滤、映射数据等)
- 终止操作
- 一旦执行终止操作就执行中间操作链,产生结果。之后不会再被使用
2.3 测试
-
创建Stream流
@Test public void test() { //通过集合 List<Integer> list = Arrays.asList(1, 2, 3); Stream<Integer> stream = list.stream(); //获取并行流 Stream<Integer> integerStream = list.parallelStream(); //通过数组 int[] arr = new int[]{1, 2, 3}; IntStream s = Arrays.stream(arr); //通过Stream的of方法 Stream<int[]> arr1 = Stream.of(arr); }
-
中间操作
@Test public void test1() { List<String> strings = Arrays.asList("Tom", "Marry", "Job", "Lily","Jack","Jack","Rose"); //过滤操作 System.out.println("----------过滤操作----------"); strings.stream().filter(s->s.contains("o")).forEach(System.out::println); //截断流 System.out.println("----------截断流----------"); strings.stream().limit(2).forEach(System.out::println); //跳过元素 System.out.println("----------跳过元素----------"); strings.stream().skip(2).forEach(System.out::println); //去重 System.out.println("----------去重----------"); strings.stream().distinct().forEach(System.out::println); //映射 System.out.println("----------映射----------"); strings.stream().map(s->s.toUpperCase()).forEach(System.out::println); //排序 System.out.println("----------排序----------"); strings.stream().sorted().forEach(System.out::println); }
-
终止操作
@Test public void test2() { List<String> strings = Arrays.asList("Tom", "Marry", "Job", "Lily", "Jack", "Jack", "Rose"); boolean j = strings.stream().allMatch(s -> s.contains("J")); System.out.println(j);//false boolean o = strings.stream().anyMatch(s -> s.contains("o")); System.out.println(o);//true boolean b = strings.stream().noneMatch(s -> s.length() > 10); System.out.println(b);//true Optional<String> first = strings.stream().findFirst(); System.out.println(first.get());//Tom long count = strings.stream().filter(s -> s.length() > 3).count(); System.out.println(count);//5 strings.stream().forEach(System.out::println); //规约 List<Integer> integers = Arrays.asList(1, 2, 3, 4, 5); Integer reduce = integers.stream().reduce(10, Integer::sum); System.out.println(reduce);//25 Optional<Integer> reduce1 = integers.stream().reduce(Integer::sum); System.out.println(reduce1.get());//15 //收集 List<String> j1 = strings.stream().filter(s -> s.startsWith("J")).collect(Collectors.toList()); System.out.println(j1.toString());//[Job, Jack, Jack] }
三、Optional类
3.1 概述
空指针异常是导致Java程序运行失败的常见原因。Optional<T>类是一个容器类,它可以保存类型T的值,代表这个值存在。或者仅仅保存null,表示这个值不存在。原来用null表示一个值不存在,现在Optional可以更好的表达这个概念。并且可以避免空指针异常。
3.2 测试
-
获取Optional容器
@Test public void test3() { String hello = new String("Hello"); //of(T t):保证t是非空 Optional<String> hello1 = Optional.of(hello); System.out.println(hello1);//Optional[Hello] hello = null; //ofNullable(T t):t可以为null Optional<String> hello2 = Optional.ofNullable(hello); System.out.println(hello2);//Optional.empty Optional<String> hello3 = Optional.of(hello); System.out.println(hello3);//java.lang.NullPointerException }
-
方法测试
@Test public void test4() { String str = null; //ofNullable(T t):t可以为null Optional<String> stringOptional = Optional.ofNullable(str); //orElse(T t1):如果当前的Optional内部封装的t是非空的,则返回t //若内部t是空,则返回orElse()方法中的参数t1 String hello = stringOptional.orElse(new String("hello")); System.out.println(hello);//hello List<String> strings = Arrays.asList("Job", "Marry", "Lily"); Optional<List<String>> list = Optional.ofNullable(strings); //get方法获取Optional容器中存储的对象 List<String> arrayList = list.get(); System.out.println(arrayList); }