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);
  }
}


目录
相关文章
|
29天前
|
自然语言处理 算法 Java
地址描述转换为坐标点不使用API,有什么转换的方法?
地址描述转换为坐标点不使用API,有什么转换的方法?
221 64
|
5天前
|
JavaScript 前端开发 Java
多种语言请求API接口方法
每种语言和库的选择取决于具体需求、项目环境以及个人偏好。了解这些基本方法,开发者就可以根据项目需求选择合适的语言和库来高效地与API交互。
15 1
|
9天前
|
安全 测试技术 API
一图看懂API测试9种方法
一图看懂API测试九种方法:冒烟测试验证基本功能,功能测试确保符合规格,集成测试检查组件协同工作,回归测试防止新变更引入问题,负载测试评估性能稳定性,压力测试挑战极限负载,安全测试发现并修复漏洞,用户界面测试确保UI与API协调,模糊测试提升异常数据处理鲁棒性。
|
4天前
|
Java 编译器 API
从Java 8到Java 17,这些新特性让你的代码起飞!
【10月更文挑战第10天】在软件开发领域,Java作为一种历史悠久且广泛使用的编程语言,不断进化以适应新的需求和挑战。从Java 8到Java 17,每一次版本更新都带来了诸多新特性和改进,极大地提升了开发效率和代码质量。今天,我们就来一起探讨这些新特性,看看它们是如何让我们的代码“起飞”的。
52 0
|
29天前
|
Java 程序员 API
Java 8新特性之Lambda表达式与Stream API的探索
【9月更文挑战第24天】本文将深入浅出地介绍Java 8中的重要新特性——Lambda表达式和Stream API,通过实例解析其语法、用法及背后的设计哲学。我们将一探究竟,看看这些新特性如何让Java代码变得更加简洁、易读且富有表现力,同时提升程序的性能和开发效率。
|
2月前
|
Java API
Java 8新特性:Lambda表达式与Stream API的深度解析
【7月更文挑战第61天】本文将深入探讨Java 8中的两个重要特性:Lambda表达式和Stream API。我们将首先介绍Lambda表达式的基本概念和语法,然后详细解析Stream API的使用和优势。最后,我们将通过实例代码演示如何结合使用Lambda表达式和Stream API,以提高Java编程的效率和可读性。
|
2月前
|
UED 开发工具 iOS开发
Uno Platform大揭秘:如何在你的跨平台应用中,巧妙融入第三方库与服务,一键解锁无限可能,让应用功能飙升,用户体验爆棚!
【8月更文挑战第31天】Uno Platform 让开发者能用同一代码库打造 Windows、iOS、Android、macOS 甚至 Web 的多彩应用。本文介绍如何在 Uno Platform 中集成第三方库和服务,如 Mapbox 或 Google Maps 的 .NET SDK,以增强应用功能并提升用户体验。通过 NuGet 安装所需库,并在 XAML 页面中添加相应控件,即可实现地图等功能。尽管 Uno 平台减少了平台差异,但仍需关注版本兼容性和性能问题,确保应用在多平台上表现一致。掌握正确方法,让跨平台应用更出色。
41 0
|
2月前
|
数据采集 API TensorFlow
简化目标检测流程:深入探讨TensorFlow Object Detection API的高效性与易用性及其与传统方法的比较分析
【8月更文挑战第31天】TensorFlow Object Detection API 是一项强大的工具,集成多种先进算法,支持 SSD、Faster R-CNN 等模型架构,并提供预训练模型,简化目标检测的开发流程。用户只需准备数据集并按要求处理,选择预训练模型进行微调训练即可实现目标检测功能。与传统方法相比,该 API 极大地减少了工作量,提供了从数据预处理到结果评估的一站式解决方案,降低了目标检测的技术门槛,使初学者也能快速搭建高性能系统。未来,我们期待看到更多基于此 API 的创新应用。
29 0
|
11天前
|
人工智能 自然语言处理 PyTorch
Text2Video Huggingface Pipeline 文生视频接口和文生视频论文API
文生视频是AI领域热点,很多文生视频的大模型都是基于 Huggingface的 diffusers的text to video的pipeline来开发。国内外也有非常多的优秀产品如Runway AI、Pika AI 、可灵King AI、通义千问、智谱的文生视频模型等等。为了方便调用,这篇博客也尝试了使用 PyPI的text2video的python库的Wrapper类进行调用,下面会给大家介绍一下Huggingface Text to Video Pipeline的调用方式以及使用通用的text2video的python库调用方式。
|
11天前
|
JSON JavaScript API
(API接口系列)商品详情数据封装接口json数据格式分析
在成长的路上,我们都是同行者。这篇关于商品详情API接口的文章,希望能帮助到您。期待与您继续分享更多API接口的知识,请记得关注Anzexi58哦!