19 Java8概述(Java8概述+lambda表达式+函数式接口+方法引用+Stream+新时间API)

简介: 19 Java8概述(Java8概述+lambda表达式+函数式接口+方法引用+Stream+新时间API)

本篇是Java基础篇分篇章最后一章

接下来会沉浸一小段时间,整理一份整合起来的大约有12w+词,40w+字符的Java基础篇Markdown笔记,并且将前期缺少的部分知识点和案例也陆续完善进去

后续更新一些综合案例和LeetCode算法题,以及Javaweb部分的框架体系等等,或许也会有一些其他杂七杂八的东西(碎碎念)

记录成长-第一阶段勉勉强强给自己打分70分


19.1 Java8概述


Java8 (又称 JKD1.8) 是 Java 语言开发的一个主要版本。

Oracle公司于2014年3月18日发布Java8 。

  • 支持Lambda表达式
  • 函数式接口
  • 新的Stream API
  • 新的日期 API
  • 其他特性

19.2 Lambda表达式


19.2.1 概念

  • Lambda表达式是特殊的匿名内部类,语法更简洁。
  • Lambda表达式允许把函数作为一个方法的参数(函数作为方法参数传递),将代码像数据一样传递。

19.2.2 语法

<函数式接口> <变量名> = (参数1,参数2…) -> {

//方法体

};

19.2.3 基本使用

演示案例:

public class Demo1 {
  public static void main(String[] args) {
    //匿名内部类
    Runnable runnable=new Runnable() {
      
      @Override
      public void run() {
        System.out.println("子线程执行了.........");
      }
    };
    
    //Lambda表达式
    Runnable runnable2=()->System.out.println("子线程执行了2.........");
    
    new Thread(runnable2).start();
    new Thread(()->System.out.println("子线程执行了3.........")).start();
    
    /
    //匿名内部类
    Comparator<String> com=new Comparator<String>() {

      @Override
      public int compare(String o1, String o2) {
        // TODO Auto-generated method stub
        return o1.length()-o2.length();
      }
    };
    
    //Lambda表达式
    
    Comparator<String> com2=(String o1, String o2)-> {
      // TODO Auto-generated method stub
      return o1.length()-o2.length();
    };
    
    Comparator<String> com3=(o1,o2)->o1.length()-o2.length();
    
    TreeSet<String> treeSet=new TreeSet<>(com3);
  }
}

Lambda引入了新的操作符:->(箭头操作符),->将表达式分成两部分:

  • 左侧:(参数1,参数2…)表示参数列表
  • 右侧:{ }内部是方法体

注意事项:

19.2.4 案例展示

Usb接口:

@FunctionalInterface
public interface Usb {
  void service();
}

TestUsb类:

public class TestUsb {
  public static void main(String[] args) {
    //匿名内部类
    Usb mouse=new Usb() {
      
      @Override
      public void service() {
        System.out.println("鼠标开始工作了..........");
      }
    };
    
    Usb fan=()->System.out.println("风扇开始工作了..........");
    
    
    run(mouse);
    run(fan);
  }
  public static void run(Usb usb) {
    usb.service();
  }
}

19.3 函数式接口


19.3.1 概念 如果一个接口只有一个抽象方法,则该接口称之为函数式接口。

函数式接口可以使用Lambda表达式,Lambda表达式会被匹配到这个抽象方法上 。

@FunctionalInterface 注解检测接口是否符合函数式接口规范。

19.3.2 常见函数式接口

接口 参数类型 返回类型 说明
Consumer< T > 消费型接口 T void void accept(T t);对类型为T的对象应用操作
Supplier< T > 供给型接口 T T get(); 返回类型为T的对象
Function< T,R > 函数型接口 T R R apply(T t);对类型为T的对象应用操作,并返回类型为R类型的对象。
Predicate< T > 断言型接口 T boolean boolean test(T t);确定类型为T的对象是否满足条件,并返回boolean类型。

案例演示:

public class TestFun {
  public static void main(String[] args) {

    //Lambda表达式
    Consumer<Double> consumer= t->System.out.println("聚餐消费:"+t);
    
    happy(t->System.out.println("聚餐消费:"+t), 1000);
    happy(t->System.out.println("唱歌消费:"+t), 2000);
    
    int[] arr=getNums(()->new Random().nextInt(100), 5);
    System.out.println(Arrays.toString(arr));
    int[] arr2=getNums(()->new Random().nextInt(1000), 10);
    System.out.println(Arrays.toString(arr2));
    
    String result=handlerString(s->s.toUpperCase(), "hello");
    System.out.println(result);
    String result2=handlerString(s->s.trim(), "   zhangsan        ");
    System.out.println(result2);
    
    List<String> list=new ArrayList<>();
    list.add("zhangsan");
    list.add("zhangwuji");
    list.add("lisi");
    list.add("wangwu");
    list.add("zhaoliu");
    List<String> result=filterNames(s->s.startsWith("zhang"), list);
    System.out.println(result.toString());
    
    List<String> result2=filterNames(s->s.length()>5, list);
    System.out.println(result2);
  }
  //Consumer 消费型接口
  public static void happy(Consumer<Double> consumer,double money) {
    consumer.accept(money);
  }
  
  //Supplier 供给型接口
  public static int[] getNums(Supplier<Integer> supplier,int count) {
    int[] arr=new int[count];
    for(int i=0;i<count;i++) {
      arr[i]=supplier.get();
    }
    return arr;
  }
  
  //Function函数型接口
  public static String handlerString(Function<String, String> function,String str) {
    return function.apply(str);
  }
  
  //Predicate 断言型接口
  
  public static List<String> filterNames(Predicate<String> predicate,List<String> list){
    List<String> resultList=new ArrayList<String>();
    for (String string : list) {
      if(predicate.test(string)) {
        resultList.add(string);
      }
    }
    return resultList;
  }
  
}

19.4 方法引用


19.4.1 概念

  • 方法引用是Lambda表达式的一种简写形式。
  • 如果Lambda表达式方法体中只是调用一个特定的已经存在的方法,则可以使用方法引用。

常见形式:

  • 对象::实例方法
  • 类::静态方法
  • 类::实例方法
  • 类::new

19.4.2 基本使用

Employee类:

publpublic class Employee {
  private String name;
  private double money;
  public Employee() {
    // TODO Auto-generated constructor stub
  }
  
  public Employee(String name, double money) {
    super();
    this.name = name;
    this.money = money;
  }

  public String getName() {
    return name;
  }
  public void setName(String name) {
    this.name = name;
  }
  public double getMoney() {
    return money;
  }
  public void setMoney(double money) {
    this.money = money;
  }
  @Override
  public String toString() {
    return "Employee [name=" + name + ", money=" + money + "]";
  }

  @Override
  public int hashCode() {
    final int prime = 31;
    int result = 1;
    long temp;
    temp = Double.doubleToLongBits(money);
    result = prime * result + (int) (temp ^ (temp >>> 32));
    result = prime * result + ((name == null) ? 0 : name.hashCode());
    return result;
  }

  @Override
  public boolean equals(Object obj) {
    if (this == obj)
      return true;
    if (obj == null)
      return false;
    if (getClass() != obj.getClass())
      return false;
    Employee other = (Employee) obj;
    if (Double.doubleToLongBits(money) != Double.doubleToLongBits(other.money))
      return false;
    if (name == null) {
      if (other.name != null)
        return false;
    } else if (!name.equals(other.name))
      return false;
    return true;
  }
  
}

TestEmployee类:

public class Demo4 {
  public static void main(String[] args) {
    //1 对象::实例方法
    Consumer<String> consumer=s->System.out.println(s);
    consumer.accept("hello");
    Consumer<String> consumer2=System.out::println;
    consumer.accept("world");
    
    //2类::静态方法
    Comparator<Integer> com=(o1,o2)->Integer.compare(o1, o2);
    Comparator<Integer> com2=Integer::compare;
      
    //3类::实例方法
    Function<Employee, String> function=e->e.getName();
    Function<Employee, String> function2=Employee::getName;
    
    System.out.println(function2.apply(new Employee("小明", 50000)));
    
    //4类::new
    Supplier<Employee> supplier=()->new Employee();
    Supplier<Employee> supplier2=Employee::new;
    
    Employee employee=supplier.get();
    System.out.println(employee.toString());
    
  }
}

19.5 Stream


19.5.1 概念

流(Stream)与集合类似,但集合中保存的是数据,而Stream中保存对集合或数组数据的操作。

19.5.2 Stream特点

  • Stream 自己不会存储元素。
  • Stream 不会改变源对象。相反,他们会返回一个持有结果的新Stream。
  • Stream 操作是延迟执行的,会等到需要结果的时候才执行。

19.5.3 Stream使用步骤

创建:

  • 新建一个流。

中间操作:

  • 在一个或多个步骤中,将初始Stream转化到另一个Stream的中间操作。

终止操作:

  • 使用一个终止操作来产生一个结果。该操作会强制之前的延迟操作立即执行,在此之后,该Stream就不能使用了。

19.5.4 创建Stream

  • 通过Collection对象的stream()或parallelStream()方法。
  • 通过Arrays类的stream()方法。
  • 通过Stream接口的of()、iterate()、generate()方法。
  • 通过IntStream、LongStream、DoubleStream接口中的of、range、rangeClosed方法。

案例演示:

public class Demo5 {
  public static void main(String[] args) {
    //(1)Collection对象中的stream()和parallelStream()方法
    ArrayList<String> arrayList=new ArrayList<>();
    arrayList.add("apple");
    arrayList.add("huawei");
    arrayList.add("xiaomi");
    Stream<String> stream = arrayList.parallelStream();
    //遍历
//    stream.forEach(s->System.out.println(s));
    stream.forEach(System.out::println);
    //(2)Arrays工具类的stream方法
    String[] arr= {"aaa","bbb","ccc"};
    Stream<String> stream2=Arrays.stream(arr);
    stream2.forEach(System.out::println);
    
    //(3)Stream接口中的of iterate 、generate 方法
    
    Stream<Integer> stream3 = Stream.of(10,20,30,40,50);
    stream3.forEach(System.out::println);
    //迭代流
    System.out.println("-----迭代流------");
    Stream<Integer> iterate = Stream.iterate(0, x->x+2);
    iterate.limit(5).forEach(System.out::println);
    System.out.println("--------生成流----------");
    //生成流
    Stream<Integer> generate = Stream.generate(()->new Random().nextInt(100));
    generate.limit(10).forEach(System.out::println);
    
    //(4)IntStream,LongStream,DoubleStream  的of  、range、rangeClosed
    IntStream stream4 = IntStream.of(100,200,300);
    stream4.forEach(System.out::println);
    IntStream range = IntStream.rangeClosed(0, 50);
    range.forEach(System.out::println);
  }
}

19.5.5 中间操作

常见中间操作:

  • filter、limit、skip、distinct、sorted
  • map
  • parallel

案例演示:

public class Demo6 {
  public static void main(String[] args) {
    ArrayList<Employee> list=new ArrayList<>();
    list.add(new Employee("小王", 15000));
    list.add(new Employee("小张", 12000));
    list.add(new Employee("小李", 18000));
    list.add(new Employee("小孙", 20000));
    list.add(new Employee("小刘", 25000));
    //list.add(new Employee("小刘", 25000));
    //中间操作1 
        //filter过滤、limit 限制、skip 跳过、distinct 去掉重复、sorted排序
    //(1) filter过滤
    System.out.println("------filter-------");
    list.stream()
      .filter(e->e.getMoney()>15000)
      .forEach(System.out::println);
    //(2) limit限制
    System.out.println("----limit------");
    list.stream()
      .limit(2)
      .forEach(System.out::println);
    //(3) skip跳过
    System.out.println("-----skip------");
    list.stream()
      .skip(2)
      .forEach(System.out::println);
    System.out.println("------distinct--------");
    //(4) distinct去重复
    list.stream()
      .distinct()
      .forEach(System.out::println);
    
    System.out.println("---------sorted---------");
    //(5) sorted排序
    list.stream()
      .sorted((e1,e2)->Double.compare(e1.getMoney(), e2.getMoney()))
      .forEach(System.out::println);
        
    //中间操作2 map
    System.out.println("---------map--------");
    list.stream()
      .map(e->e.getName())
      .forEach(System.out::println);
    //中间操作3 parallel 采用多线程 效率高
    System.out.println("---------map--------");
    list.parallelStream()
      .forEach(System.out::println);
  }
}

串行流和并行流:

  • 串行流使用单线程。
  • 并行流使用多线程,效率更高。
public class Demo7 {
  public static void main(String[] args) {
    //串行流和并行流的区别
    ArrayList<String> list=new ArrayList<>();
    for(int i=0;i<5000000;i++) {
      list.add(UUID.randomUUID().toString());
    }
    //串行:10秒  并行:7秒
    long start=System.currentTimeMillis();
        long count=list.Stream().sorted().count();
    //long count=list.parallelStream().sorted().count();
    System.out.println(count);
    long end=System.currentTimeMillis();
    System.out.println("用时:"+(end-start));
  }
}

19.5.6 终止操作

常见终止操作:

  • forEach、min、max、count
  • reduce、collect

案例演示:

public class Demo8 {
  public static void main(String[] args) {
    ArrayList<Employee> list = new ArrayList<>();
    list.add(new Employee("小王", 15000));
    list.add(new Employee("小张", 12000));
    list.add(new Employee("小李", 18000));
    list.add(new Employee("小孙", 20000));
    list.add(new Employee("小刘", 25000));
    //1 终止操作 foreach
    list.stream()
      .filter(e->{
          System.out.println("过滤了....");
          return e.getMoney()>15000;
        })
      .forEach(System.out::println);
    //2 终止操作 min max count
    System.out.println("-----min-----");
    Optional<Employee> min = list.stream()
      .min((e1,e2)->Double.compare(e1.getMoney(), e2.getMoney()));
    System.out.println(min.get());
    System.out.println("-----max-----");
    Optional<Employee> max = list.stream()
      .max((e1,e2)->Double.compare(e1.getMoney(), e2.getMoney()));
    System.out.println(max.get());
    
    long count = list.stream().count();
    System.out.println("员工个数:"+count);
    
    //3 终止操作 reduce 规约
    //计算所有员工的工资和
    System.out.println("--------reduce---------");
    Optional<Double> sum = list.stream()
      .map(e->e.getMoney())
      .reduce((x,y)->x+y);
    System.out.println(sum.get());
    
    //4 终止方法 collect收集
    //获取所有的员工姓名,封装成一个list集合
    System.out.println("------collect------");
    List<String> names = list.stream()
      .map(e->e.getName())
      .collect(Collectors.toList());
    for (String string : names) {
      System.out.println(string);
    }
  }
}

19.6 新时间API


19.6.1 概述

之前时间API存在问题:线程安全问题、设计混乱。

本地化日期时间 API:

  • LocalDate
  • LocalTime
  • LocalDateTime

Instant:时间戳。

ZoneId:时区。

Date、Instant、LocalDateTime的转换。

DateTimeFormatter:格式化类。

19.6.2 LocalDateTime类

表示本地日期时间,没有时区信息

public class Demo2 {
  public static void main(String[] args) {
    //1创建本地时间
    LocalDateTime localDateTime=LocalDateTime.now();
    //LocalDateTime localDateTime2=LocalDateTime.of(year, month, dayOfMonth, hour, minute)
    System.out.println(localDateTime);
    System.out.println(localDateTime.getYear());
    System.out.println(localDateTime.getMonthValue());
    System.out.println(localDateTime.getDayOfMonth());
    
    //2添加两天
    LocalDateTime localDateTime2 = localDateTime.plusDays(2);
    System.out.println(localDateTime2);
    
    //3减少一个月
    LocalDateTime localDateTime3 = localDateTime.minusMonths(1);
    System.out.println(localDateTime3);
  }
}

19.6.3 Instant、ZoneId类

Instant表示瞬间;和前面Date类似。

ZoneId表示时区信息。

public class Demo3 {
  public static void main(String[] args) {
    //1 创建Instant:时间戳
    Instant instant=Instant.now();
    System.out.println(instant.toString());
    System.out.println(instant.toEpochMilli());
    System.out.println(System.currentTimeMillis());
    //2 添加减少时间
    
    Instant instant2 = instant.plusSeconds(10);
    
    System.out.println(Duration.between(instant, instant2).toMillis());
    
    //3ZoneId
    Set<String> availableZoneIds = ZoneId.getAvailableZoneIds();
    for (String string : availableZoneIds) {
      System.out.println(string);
    }
    
    System.out.println(ZoneId.systemDefault().toString());
    
    //1 Date --->Instant--->LocalDateTime
    System.out.println("-------------Date --->Instant---->LocalDateTime-----------");
    Date date=new Date();
    Instant instant3 = date.toInstant();
    System.out.println(instant3);
    
    LocalDateTime localDateTime = LocalDateTime.ofInstant(instant3, ZoneId.systemDefault());
    System.out.println(localDateTime);
    
    //2 LocalDateTime --->Instant--->Date
    System.out.println("-------------LocalDateTime --->Instant---->Date-----------");
  
    Instant instant4 = localDateTime.atZone(ZoneId.systemDefault()).toInstant();
    System.out.println(instant4);
    Date from = Date.from(instant4);
    System.out.println(from);
    
  }
}

19.6.4 DateTimeFormatter类

DateTimeFormatter是时间格式化类。

public class Demo4 {
  public static void main(String[] args) {
    //创建DateTimeFormatter
    DateTimeFormatter dtf=DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss");
    //1 把时间格式化成字符串
    String format = dtf.format(LocalDateTime.now());
    System.out.println(format);
    //2 把字符串解析成时间
    LocalDateTime localDateTime = LocalDateTime.parse("2020/03/10 10:20:35", dtf);
    System.out.println(localDateTime);
  }
}

stant instant4 = localDateTime.atZone(ZoneId.systemDefault()).toInstant();
    System.out.println(instant4);
    Date from = Date.from(instant4);
    System.out.println(from);
    
  }
}

19.6.4 DateTimeFormatter类

DateTimeFormatter是时间格式化类。

public class Demo4 {
  public static void main(String[] args) {
    //创建DateTimeFormatter
    DateTimeFormatter dtf=DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss");
    //1 把时间格式化成字符串
    String format = dtf.format(LocalDateTime.now());
    System.out.println(format);
    //2 把字符串解析成时间
    LocalDateTime localDateTime = LocalDateTime.parse("2020/03/10 10:20:35", dtf);
    System.out.println(localDateTime);
  }
}


目录
相关文章
|
24天前
|
JSON 安全 API
淘宝商品详情API接口(item get pro接口概述)
淘宝商品详情API接口旨在帮助开发者获取淘宝商品的详细信息,包括商品标题、描述、价格、库存、销量、评价等。这些信息对于电商企业而言具有极高的价值,可用于商品信息展示、市场分析、价格比较等多种应用场景。
|
1月前
|
数据采集 监控 数据挖掘
常用电商商品数据API接口(item get)概述,数据分析以及上货
电商商品数据API接口(item get)是电商平台上用于提供商品详细信息的接口。这些接口允许开发者或系统以编程方式获取商品的详细信息,包括但不限于商品的标题、价格、库存、图片、销量、规格参数、用户评价等。这些信息对于电商业务来说至关重要,是商品数据分析、价格监控、上货策略制定等工作的基础。
|
1月前
|
Java API 开发者
Java中的Lambda表达式与Stream API的协同作用
在本文中,我们将探讨Java 8引入的Lambda表达式和Stream API如何改变我们处理集合和数组的方式。Lambda表达式提供了一种简洁的方法来表达代码块,而Stream API则允许我们对数据流进行高级操作,如过滤、映射和归约。通过结合使用这两种技术,我们可以以声明式的方式编写更简洁、更易于理解和维护的代码。本文将介绍Lambda表达式和Stream API的基本概念,并通过示例展示它们在实际项目中的应用。
|
2月前
|
Java API 开发者
Java中的Lambda表达式:简洁代码的利器####
本文探讨了Java中Lambda表达式的概念、用途及其在简化代码和提高开发效率方面的显著作用。通过具体实例,展示了Lambda表达式如何在Java 8及更高版本中替代传统的匿名内部类,使代码更加简洁易读。文章还简要介绍了Lambda表达式的语法和常见用法,帮助开发者更好地理解和应用这一强大的工具。 ####
|
1月前
|
安全 Java API
Java中的Lambda表达式:简化代码的现代魔法
在Java 8的发布中,Lambda表达式的引入无疑是一场编程范式的革命。它不仅让代码变得更加简洁,还使得函数式编程在Java中成为可能。本文将深入探讨Lambda表达式如何改变我们编写和维护Java代码的方式,以及它是如何提升我们编码效率的。
|
2月前
|
安全 Java API
Java中的Lambda表达式与Stream API的高效结合####
探索Java编程中Lambda表达式与Stream API如何携手并进,提升数据处理效率,实现代码简洁性与功能性的双重飞跃。 ####
35 0
|
Java Unix 数据库管理
java定时框架:表达式设置
Quartz中时间表达式的设置-----corn表达式 (注:这是让我看比较明白的一个博文,但是抱歉,没有找到原作者,如有侵犯,请告知)   时间格式: ,   分别对应: 秒>分>小时>日>月>周>年,  举例: 1.
879 0
|
14天前
|
监控 Java
java异步判断线程池所有任务是否执行完
通过上述步骤,您可以在Java中实现异步判断线程池所有任务是否执行完毕。这种方法使用了 `CompletionService`来监控任务的完成情况,并通过一个独立线程异步检查所有任务的执行状态。这种设计不仅简洁高效,还能确保在大量任务处理时程序的稳定性和可维护性。希望本文能为您的开发工作提供实用的指导和帮助。
68 17
|
25天前
|
Java
Java—多线程实现生产消费者
本文介绍了多线程实现生产消费者模式的三个版本。Version1包含四个类:`Producer`(生产者)、`Consumer`(消费者)、`Resource`(公共资源)和`TestMain`(测试类)。通过`synchronized`和`wait/notify`机制控制线程同步,但存在多个生产者或消费者时可能出现多次生产和消费的问题。 Version2将`if`改为`while`,解决了多次生产和消费的问题,但仍可能因`notify()`随机唤醒线程而导致死锁。因此,引入了`notifyAll()`来唤醒所有等待线程,但这会带来性能问题。
Java—多线程实现生产消费者
|
10天前
|
缓存 安全 算法
Java 多线程 面试题
Java 多线程 相关基础面试题