Java8新特性

 
 
 
 一、Lambda表达式
 
  • Lambda 是一个匿名函数,我们可以把Lambda 表达式理解为是一段可以传递的代码(将代码像数据一样进行传递)。使用它可以写出更简洁、更灵活的代码。作为一种更紧凑的代码风格,使Java的语言表达能力得到了提升。

  • 格式:  
    •  lambda操作符或箭头操作符
    • 左边:lambda形参列表(其实就是借口中的抽象方法的形参列表)
    • 右边:lambda体(其实就是重写的抽象方法的方法体)
  • lambda表达式的本质:作为接口的实例

 

 

lambda表达式举例:

  • 语法格式一:无参,无返回值
复制代码
 1  public class Test02 {
 2      int num = 10; //jdk 1.7以前 必须final修饰
 3      
 4      @Test
 5      public void test01(){
 6          //匿名内部类
 7          new Runnable() {
 8              @Override
 9              public void run() {
10                  //在局部类中引用同级局部变量
11                  //只读
12                  System.out.println("Hello World" + num);
13              }
14          };
15      }
16  
17      @Test
18      public void test02(){
19          //lambda表达式
20          Runnable runnable = () -> {
21              System.out.println("Hello Lambda,我是run()函数");
22          };
23      }
24  }
复制代码

 

  • 语法格式二 :有一个参数,没有返回值
  • 语法格式三:若只有一个参数,小括号可以省略不写 a -> System.out.println(a)
  • 语法格式四:数据类型可以省略不写,由JVM编译器通过上下文推断得出
1  @Test
2  public void test03(){
3      Consumer<String> consumer = (a) -> System.out.println(a);
4      consumer.accept("我省略了accept函数名!");
5  }

 

 

  • 语法格式五:Lambda需要两个或以上的参数,多条执行语句,并且可以有返回值
1  @Test
2  public void test04(){
3      Comparator<Integer> comparator = (a, b) -> {
4          System.out.println("比较接口");
5          return Integer.compare(a, b);
6      };
7  }
  • 语法格式六:当若 Lambda 体中只有一条语句, return 和 大括号都可以省略不写
1  Comparator<Integer> com = (x, y) -> Integer.compare(x, y);

 

 

二、函数式接口

  • 如果一个接口中,只声明了一个抽象方法,则此接口就称为函数式接口

java内置四大核心函数式接口 

 

 

  •  消费型接口
复制代码
 1 /**
 2  * Consumer<T> 消费型接口 :
 3  */
 4 @Test
 5 public void consumerTest() {
 6     happy(2999.99, m -> System.out.println("此次消费了:" + m + "元"));
 7 }
 8 
 9 public void happy(Double money, Consumer<Double> consumer) {
10     consumer.accept(money);
11 }
复制代码

 

 

  • 提供型接口
复制代码
 1 /**
 2  * Supplier<T> 供给型接口 :
 3  */
 4 @Test
 5 public void supplierTest() {
 6     Random random = new Random();
 7     List<Integer> numList = getNumList(10, () -> random.nextInt(100));
 8     numList.forEach(System.out::println);
 9 }
10 
11 /**
12  * 需求:产生指定个数的整数,并放入集合中
13  *
14  * @param num
15  * @param sup
16  * @return
17  */
18 public List<Integer> getNumList(int num, Supplier<Integer> sup) {
19     List<Integer> list = new ArrayList<>();
20 
21     for (int i = 0; i < num; i++) {
22         Integer n = sup.get();
23         list.add(n);
24     }
25 
26     return list;
27 }
复制代码

 

 

  • 函数型接口
复制代码
 1 /**
 2  * Function<T, R> 函数型接口
 3  */
 4 @Test
 5 public void functionTest() {
 6     // s -> s.trim() 可替换成 String::trim
 7     String newStr = strHandler("\t\t\t 威武   ", s -> s.trim());
 8     System.out.println(newStr);
 9 
10     String subStr = strHandler("  威武呀", s -> s.substring(2, 5));
11     System.out.println(subStr);
12 }
13 
14 /**
15  * 需求:用于处理字符串
16  *
17  * @param str
18  * @param fun
19  * @return
20  */
21 public String strHandler(String str, Function<String, String> fun) {
22     return fun.apply(str);
23 }
复制代码

 

 

  • 断言型接口
复制代码
 1 /**
 2  * Predicate<T> 断言型接口:
 3  */
 4 @Test
 5 public void predicateTest(){
 6     List<String> list = Arrays.asList("Hello", "yxj", "Lambda", "www", "ok");
 7     List<String> strings = filterStr(list, p -> p.length() > 3);
 8     strings.forEach(System.out::println);
 9 }
10 
11 /**
12  * 需求:将满足条件的字符串,放入集合中
13  *
14  * @param list
15  * @param pre
16  * @return
17  */
18 public List<String> filterStr(List<String> list, Predicate<String> pre) {
19     List<String> strList = new ArrayList<>();
20 
21     for (String str : list) {
22         if (pre.test(str)) {
23             strList.add(str);
24         }
25     }
26 
27     return strList;
28 }
复制代码

 

 

三、方法引用和构造器引用

(1)

1.方法引用:若 Lambda 体中的功能,已经有方法提供了实现,可以使用方法引用(可以将方法引用理解为 Lambda 表达式的另外一种表现形式)

2.方法引用本质上就是lambda表达式

3.使用格式:  类(或对象) ::方法名

4.具体分为如下三种情况:

  对象 ::非静态方法

  类::静态方法

  类::非静态方法

 

①:

复制代码
 1 /**
 2  * 对象::实例方法
 3  */
 4 @Test
 5 public void test01() {
 6     PrintStream printStream = System.out;
 7     Consumer<String> consumer = s -> printStream.println(s);
 8     consumer.accept("aaa");
 9 
10     Consumer<String> consumer2 = printStream::println;
11     consumer2.accept("bbb");
12 }
13 
14 @Test
15 public void test02(){
16     Employee emp = new Employee(101, "张三", 18, 9999.99);
17     Supplier<String> supplier = ()->emp.getName();
18     System.out.println(supplier.get());
19 
20     Supplier<String> supplier2 = emp::getName;
21     System.out.println(supplier2.get());
22 }
23 
24 @Test
25 public void test03(){
26     BiFunction<Double, Double, Double> fun = (x, y) -> Math.max(x, y);
27     Double apply = fun.apply(99.99, 199.99);
28     System.out.println(apply);
29 
30     BiFunction<Double, Double, Double> fun2 = Math::max;
31     Double apply1 = fun2.apply(88.88, 188.88);
32     System.out.println(apply1);
33 }
复制代码

 

复制代码
 1 /**
 2  * 类名 :: 静态方法名
 3  */
 4 @Test
 5 public void test02() {
 6     Comparator<Integer> comparator = (a, b) -> Integer.compare(a, b);
 7     System.out.println(comparator.compare(1, 2));
 8 
 9     Comparator<Integer> comparator2 = Integer::compare;
10     System.out.println(comparator2.compare(10, 20));
11 }
复制代码

 

复制代码
 1 /**
 2  * 类名 :: 实例方法名
 3  */
 4 @Test
 5 public void test05() {
 6     BiPredicate<String, String> bp = (x, y) -> x.equals(y);
 7     boolean test = bp.test("hello word", "hello future");
 8 
 9     BiPredicate<String, String> bp2 = String::equals;
10     boolean test2 = bp2.test("hello word", "hello future");
11 
12     System.out.println("-----------------------------------------");
13 
14     Function<Employee, String> function = e -> e.show();
15     String apply = function.apply(new Employee());
16     System.out.println(apply);
17 
18     Function<Employee, String> function2 = Employee::show;
19     String apply1 = function2.apply(new Employee());
20     System.out.println(apply1);
21 }
复制代码

 


(2)构造器引用

复制代码
 1 /**
 2  * 构造器引用
 3  */
 4 @Test
 5 public void test06() {
 6     Supplier<Employee> supplier = () -> new Employee();
 7     Employee employee = supplier.get();
 8     System.out.println(employee);
 9 
10     Supplier<Employee> supplier1 = Employee::new;
11     Employee employee1 = supplier1.get();
12     System.out.println(employee1);
13 }
14 
15 @Test
16 public void test07(){
17     Supplier<List> supplier = ()->new ArrayList<Integer>();
18     List list = supplier.get();
19     list.add(1);
20     list.add(2);
21     System.out.println(list);
22 
23     Supplier<List> supplier1 = ArrayList::new;
24     List list1 = supplier1.get();
25     System.out.println(list1);
26 }
复制代码

 


(3)数组引用
复制代码
 1 /**
 2  * 数组引用
 3  */
 4 @Test
 5 public void test08(){
 6     Function<Integer, String[]> fun = (args)->new String[args];
 7     String[] apply = fun.apply(10);
 8     System.out.println("apply.length = " + apply.length);
 9 
10     System.out.println("--------------------------");
11 
12     Function<Integer, Employee[]> fun2 = Employee[]::new;
13     Employee[] apply1 = fun2.apply(20);
14     System.out.println("apply1.length = " + apply1.length);
15 }
复制代码

 

 

四、Stream API

注意:产生一个全新的流,和原来的数据源没有关系(数据源不受影响)!!!

 

Stream 的操作三个步骤

  • 创建 Stream
    • 一个数据源(如:集合、数组),获取一个流
  • 中间操作
    • 一个中间操作链,对数据源的数据进行处理
  • 终止操作(终端操作)
    • 一个终止操作,执行中间操作链,并产生结果

 

 ①Stream的创建(实例化)

复制代码
 1 /**
 2 * 创建流
 3 */
 4 @Test
 5 public void test01(){
 6     /**
 7     * 方式一:集合流
 8     *  - Collection.stream() 串行流
 9     *  - Collection.parallelStream() 并行流
10     */
11     List<String> list = new ArrayList<>();
12     Stream<String> stream1 = list.stream();
13 
14     //方式二:数组流
15     //Arrays.stream(array)
16     String[] strings = new String[10];
17     Stream<String> stream2 = Arrays.stream(strings);
18 
19     //方式三:Stream 静态方法
20     //Stream.of(...)
21     Stream<Integer> stream3 = Stream.of(1, 2, 3);
22 
23     //方式四:无限流(了解)
24     //迭代
25     Stream<Integer> stream4 = Stream.iterate(0, (i) -> i+2);
26     stream4.forEach(System.out::println);
27 
28     //生成
29     Stream.generate(() -> Math.random())
30         .limit(5)
31         .forEach(System.out::println);
32 }
复制代码

 

 

②Stream的中间操作

 

filter:筛选与切片

复制代码
 1    //2. 中间操作
 2    List<Employee> emps = Arrays.asList(
 3            new Employee(102, "李四", 59, 6666.66),
 4            new Employee(101, "张三", 18, 9999.99),
 5            new Employee(103, "王五", 28, 3333.33),
 6            new Employee(104, "赵六", 8, 7777.77),
 7            new Employee(104, "赵六", 8, 7777.77),
 8            new Employee(104, "赵六", 8, 7777.77),
 9            new Employee(105, "田七", 38, 5555.55)
10    );
11 
12    //内部迭代:迭代操作 Stream API 内部完成
13    @Test
14    public void test2(){
15        //所有的中间操作不会做任何的处理
16        Stream<Employee> stream = emps.stream()
17                .filter((e) -> {
18                    System.out.println("测试中间操作");
19                    // 加 return 原因:因为lambda表达式中,如果有多条语句,需要用大括号括起来,最后一句为返回语句,要加return
20                    return e.getAge() <= 35;
21                });
22 
23        //只有当做终止操作时,所有的中间操作会一次性的全部执行,称为“惰性求值”
24        stream.forEach(System.out::println);
25    }
26 
27    //外部迭代
28    @Test
29    public void test3(){
30        Iterator<Employee> it = emps.iterator();
31 
32        while(it.hasNext()){
33            System.out.println(it.next());
34        }
35    }
复制代码

 

 

limit:截断流

复制代码
1 @Test
2 public void test4(){
3     emps.stream()
4             .filter((e) -> {
5                 System.out.println("短路!"); // &&  ||
6                 return e.getSalary() >= 5000;
7             }).limit(3)
8             .forEach(System.out::println);
9 }
复制代码

 

 

skip(n):跳过元素

1 @Test
2 public void test5() {
3     emps.parallelStream()
4             .filter((e) -> e.getSalary() >= 5000)
5             .skip(2)
6             .forEach(System.out::println);
7 }

 

 

distinct:筛选

1 @Test
2 public void test6() {
3     emps.stream()
4             .distinct()
5             .forEach(System.out::println);
6 }

 

需要重写hashCode()和equals()方法


映射:

 

 

排序:

 

 


(3)Stream的终止操作

查找/匹配

 

 归约

 

 

收集

 

 

复制代码
 1 /**
 2  * 把员工的名字收集到指定的集合中
 3  */
 4 @Test
 5 public void test08(){
 6     List<String> list = emps.stream().map(Employee::getName).collect(Collectors.toList());
 7     list.forEach(System.out::println);
 8 
 9     System.out.println("--------------");
10 
11     Set<String> set = emps.stream().map(Employee::getName).collect(Collectors.toSet());
12     set.forEach(System.out::println);
13 
14     System.out.println("--------------");
15 
16     Map<Long, String> collect = emps.stream().collect(Collectors.toMap(Employee::getId, Employee::getName));
17     System.out.println(collect);
18 }
复制代码

 


五、Optional类
Optional 类 (java.util.Optional) 是一个容器类,代表一个值存在或不存在,原来用 null 表示一个值不存在,现在用 Optional 可以更好的表达这个概念;并且可以避免空指针异常

  • Optional.of(T t):创建一个 Optional 实例
  • Optional.empty(T t):创建一个空的 Optional 实例
  • Optional.ofNullable(T t):若 t 不为 null,创建 Optional 实例,否则空实例
  • isPresent():判断是否包含某值
  • orElse(T t):如果调用对象包含值,返回该值,否则返回 t
  • orElseGet(Supplier s):如果调用对象包含值,返回该值,否则返回 s 获取的值
  • map(Function f):如果有值对其处理,并返回处理后的 Optional,否则返回 Optional.empty()
  • flatmap(Function mapper):与 map 相似,要求返回值必须是 Optional

 

复制代码
 1 @Test
 2 public void test01(){
 3     Optional<Employee> employee = Optional.of(new Employee());
 4     System.out.println(employee.get());
 5 
 6     System.out.println("==========");
 7 
 8     Optional<Object> o = Optional.of(null);
 9     System.out.println(o.get());
10 }
复制代码

 






















 

posted @   草莓小甜心  阅读(32)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET10 - 预览版1新功能体验(一)
点击右上角即可分享
微信分享提示