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


目录
相关文章
|
7天前
|
运维 Java 程序员
Java中的异常处理方法
本文深入剖析Java异常处理机制,介绍可检查异常、运行时异常和错误的区别与处理方式。通过最佳实践方法,如使用合适的异常类型、声明精确异常、try-with-resources语句块、记录异常信息等,帮助开发者提高代码的可靠性、可读性和可维护性。良好的异常处理能保证程序稳定运行,避免资源泄漏和潜在问题。
|
7天前
|
传感器 监控 Java
Java代码结构解析:类、方法、主函数(1分钟解剖室)
### Java代码结构简介 掌握Java代码结构如同拥有程序世界的建筑蓝图,类、方法和主函数构成“黄金三角”。类是独立的容器,承载成员变量和方法;方法实现特定功能,参数控制输入环境;主函数是程序入口。常见错误包括类名与文件名不匹配、忘记static修饰符和花括号未闭合。通过实战案例学习电商系统、游戏角色控制和物联网设备监控,理解类的作用、方法类型和主函数任务,避免典型错误,逐步提升编程能力。 **脑图速记法**:类如太空站,方法即舱段;main是发射台,static不能换;文件名对仗,括号要成双;参数是坐标,void不返航。
27 5
|
26天前
|
Java API
java.time常用方法汇总
`java.time` API 是从 Java 8 开始引入的时间日期处理库,旨在替代老旧的 `java.util.Date` 和 `Calendar`。它提供了更简洁、强大和灵活的方式处理日期、时间、时区及时间间隔,支持全球化和时间计算需求。API 包含获取当前时间、创建指定时间、解析和格式化字符串、进行加减运算、比较时间、获取年月日时分秒、计算时间间隔、时区转换以及判断闰年等功能。示例代码展示了如何使用这些功能,极大简化了开发中的时间处理任务。
|
1月前
|
API PHP 开发者
速卖通商品详情接口(速卖通API系列)
速卖通(AliExpress)是阿里巴巴旗下的跨境电商平台,提供丰富的商品数据。通过速卖通开放平台(AliExpress Open API),开发者可获取商品详情、订单管理等数据。主要功能包括商品搜索、商品详情、订单管理和数据报告。商品详情接口aliexpress.affiliate.productdetail.get用于获取商品标题、价格、图片等详细信息。开发者需注册账号并创建应用以获取App Key和App Secret,使用PHP等语言调用API。该接口支持多种请求参数和返回字段,方便集成到各类电商应用中。
|
26天前
|
JSON 前端开发 API
以项目登录接口为例-大前端之开发postman请求接口带token的请求测试-前端开发必学之一-如果要学会联调接口而不是纯写静态前端页面-这个是必学-本文以优雅草蜻蜓Q系统API为实践来演示我们如何带token请求接口-优雅草卓伊凡
以项目登录接口为例-大前端之开发postman请求接口带token的请求测试-前端开发必学之一-如果要学会联调接口而不是纯写静态前端页面-这个是必学-本文以优雅草蜻蜓Q系统API为实践来演示我们如何带token请求接口-优雅草卓伊凡
61 5
以项目登录接口为例-大前端之开发postman请求接口带token的请求测试-前端开发必学之一-如果要学会联调接口而不是纯写静态前端页面-这个是必学-本文以优雅草蜻蜓Q系统API为实践来演示我们如何带token请求接口-优雅草卓伊凡
|
6天前
|
机器学习/深度学习 JSON 算法
淘宝拍立淘按图搜索API接口系列的应用与数据解析
淘宝拍立淘按图搜索API接口是阿里巴巴旗下淘宝平台提供的一项基于图像识别技术的创新服务。以下是对该接口系列的应用与数据解析的详细分析
|
25天前
|
监控 供应链 搜索推荐
亚马逊商品详情接口(亚马逊 API 系列)
亚马逊作为全球最大的电商平台之一,提供了丰富的商品资源。开发者和电商从业者可通过亚马逊商品详情接口获取商品的描述、价格、评论、排名等数据,对市场分析、竞品研究、价格监控及业务优化具有重要价值。接口基于MWS服务,支持HTTP/HTTPS协议,需注册并获得API权限。Python示例展示了如何使用mws库调用接口获取商品详情。应用场景包括价格监控、市场调研、智能选品、用户推荐和库存管理等,助力电商运营和决策。
93 23
|
26天前
|
JSON 数据挖掘 API
lazada商品详情接口 (lazada API系列)
Lazada 是东南亚知名电商平台,提供海量商品资源。通过其商品详情接口,开发者和商家可获取商品标题、价格、库存、描述、图片、用户评价等详细信息,助力市场竞争分析、商品优化及库存管理。接口采用 HTTP GET 请求,返回 JSON 格式的响应数据,支持 Python 等语言调用。应用场景包括竞品分析、价格趋势研究、用户评价分析及电商应用开发,为企业决策和用户体验提升提供有力支持。
86 21
|
23天前
|
JSON API 数据格式
eBay商品详情接口(ebay API系列)
eBay 商品详情接口是电商从业者、开发者和数据分析师获取商品详细信息的重要工具,涵盖标题、价格、库存、卖家信息等。使用前需在 eBay 开发者平台注册并获取 API 凭证,通过 HTTP GET 请求调用接口,返回 JSON 格式数据。Python 示例代码展示了如何发送请求并解析响应,确保合法合规使用数据。
57 12
|
22天前
|
JSON API 数据格式
阿里巴巴商品详情接口(阿里巴巴 API 系列)
在电商开发中,获取阿里巴巴商品详情信息对数据分析、竞品研究等至关重要。通过调用其商品详情接口,开发者可获取标题、价格、图片、描述等数据,满足多种业务需求。接口采用HTTPS协议,支持GET/POST请求,返回JSON格式数据。示例代码展示了如何使用Python的requests库进行接口请求,需传递商品ID和访问令牌。实际应用时,请依据官方文档调整参数并确保安全性。
52 10

热门文章

最新文章