19 Java8概述(Java8概述+lambda表达式+函数式接口+方法引用+Stream+新时间API)
创始人
2024-05-21 22:29:23

本篇是Java基础篇分篇章最后一章
接下来会沉浸一小段时间,整理一份整合起来的大约有12w+词,40w+字符的Java基础篇Markdown笔记,并且将前期缺少的部分知识点和案例也陆续完善进去
后续更新一些综合案例和LeetCode算法题,以及Javaweb部分的框架体系等等,或许也会有一些其他杂七杂八的东西(碎碎念)

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

最后散装Java基础篇最后一篇

    • 19.1 Java8概述
    • 19.2 Lambda表达式
      • 19.2.1 概念
      • 19.2.2 语法
      • 19.2.3 基本使用
      • 19.2.4 案例展示
    • 19.3 函数式接口
      • 19.3.1 概念
      • 19.3.2 常见函数式接口
    • 19.4 方法引用
      • 19.4.1 概念
      • 19.4.2 基本使用
    • 19.5 Stream
      • 19.5.1 概念
      • 19.5.2 Stream特点
      • 19.5.3 Stream使用步骤
      • 19.5.4 创建Stream
      • 19.5.5 中间操作
      • 19.5.6 终止操作
    • 19.6 新时间API
      • 19.6.1 概述
      • 19.6.2 LocalDateTime类
      • 19.6.3 Instant、ZoneId类
      • 19.6.4 DateTimeFormatter类
      • 19.6.4 DateTimeFormatter类

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() {@Overridepublic void run() {System.out.println("子线程执行了.........");}};//Lambda表达式Runnable runnable2=()->System.out.println("子线程执行了2.........");new Thread(runnable2).start();new Thread(()->System.out.println("子线程执行了3.........")).start();///匿名内部类Comparator com=new Comparator() {@Overridepublic int compare(String o1, String o2) {// TODO Auto-generated method stubreturn o1.length()-o2.length();}};//Lambda表达式Comparator com2=(String o1, String o2)-> {// TODO Auto-generated method stubreturn o1.length()-o2.length();};Comparator com3=(o1,o2)->o1.length()-o2.length();TreeSet treeSet=new TreeSet<>(com3);}
}

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

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

注意事项:

  • 形参列表的数据类型会自动推断。
  • 如果形参列表为空,只需保留() 。
  • 如果形参只有1个,()可以省略,只需要参数的名称即可。
  • 如果执行语句只有一句,且无返回值,{}可以省略,若有返回值,则若想省去{},则必须同时省略return,且执行语句也保证只有一句。
  • Lambda不会生成一个单独的内部类文件。

19.2.4 案例展示

Usb接口:

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

TestUsb类:

public class TestUsb {public static void main(String[] args) {//匿名内部类Usb mouse=new Usb() {@Overridepublic 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 > 消费型接口Tvoidvoid accept(T t);对类型为T的对象应用操作
Supplier< T > 供给型接口TT get(); 返回类型为T的对象
Function< T,R > 函数型接口TRR apply(T t);对类型为T的对象应用操作,并返回类型为R类型的对象。
Predicate< T > 断言型接口Tbooleanboolean test(T t);确定类型为T的对象是否满足条件,并返回boolean类型。

案例演示:

public class TestFun {public static void main(String[] args) {//Lambda表达式Consumer 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 list=new ArrayList<>();list.add("zhangsan");list.add("zhangwuji");list.add("lisi");list.add("wangwu");list.add("zhaoliu");List result=filterNames(s->s.startsWith("zhang"), list);System.out.println(result.toString());List result2=filterNames(s->s.length()>5, list);System.out.println(result2);}//Consumer 消费型接口public static void happy(Consumer consumer,double money) {consumer.accept(money);}//Supplier 供给型接口public static int[] getNums(Supplier supplier,int count) {int[] arr=new int[count];for(int i=0;iarr[i]=supplier.get();}return arr;}//Function函数型接口public static String handlerString(Function function,String str) {return function.apply(str);}//Predicate 断言型接口public static List filterNames(Predicate predicate,List list){List resultList=new ArrayList();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类:

public 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;}@Overridepublic String toString() {return "Employee [name=" + name + ", money=" + money + "]";}@Overridepublic 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;}@Overridepublic 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 consumer=s->System.out.println(s);consumer.accept("hello");Consumer consumer2=System.out::println;consumer.accept("world");//2类::静态方法Comparator com=(o1,o2)->Integer.compare(o1, o2);Comparator com2=Integer::compare;//3类::实例方法Function function=e->e.getName();Function function2=Employee::getName;System.out.println(function2.apply(new Employee("小明", 50000)));//4类::newSupplier supplier=()->new Employee();Supplier 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 arrayList=new ArrayList<>();arrayList.add("apple");arrayList.add("huawei");arrayList.add("xiaomi");Stream stream = arrayList.parallelStream();//遍历
//		stream.forEach(s->System.out.println(s));stream.forEach(System.out::println);//(2)Arrays工具类的stream方法String[] arr= {"aaa","bbb","ccc"};Stream stream2=Arrays.stream(arr);stream2.forEach(System.out::println);//(3)Stream接口中的of iterate 、generate 方法Stream stream3 = Stream.of(10,20,30,40,50);stream3.forEach(System.out::println);//迭代流System.out.println("-----迭代流------");Stream iterate = Stream.iterate(0, x->x+2);iterate.limit(5).forEach(System.out::println);System.out.println("--------生成流----------");//生成流Stream generate = Stream.generate(()->new Random().nextInt(100));generate.limit(10).forEach(System.out::println);//(4)IntStream,LongStream,DoubleStream  的of  、range、rangeClosedIntStream 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 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 mapSystem.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 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 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 终止操作 foreachlist.stream().filter(e->{System.out.println("过滤了....");return e.getMoney()>15000;}).forEach(System.out::println);//2 终止操作 min max countSystem.out.println("-----min-----");Optional min = list.stream().min((e1,e2)->Double.compare(e1.getMoney(), e2.getMoney()));System.out.println(min.get());System.out.println("-----max-----");Optional 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 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 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());//3ZoneIdSet availableZoneIds = ZoneId.getAvailableZoneIds();for (String string : availableZoneIds) {System.out.println(string);}System.out.println(ZoneId.systemDefault().toString());//1 Date --->Instant--->LocalDateTimeSystem.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--->DateSystem.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) {//创建DateTimeFormatterDateTimeFormatter 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) {//创建DateTimeFormatterDateTimeFormatter 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.5公里,是世界上最崇拜树木并以树为神的枪手部落...
世界上最漂亮的人 世界上最漂亮... 此前在某网上,选出了全球265万颜值姣好的女性。从这些数量庞大的女性群体中,人们投票选出了心目中最美...
长白山自助游攻略 吉林长白山游... 昨天介绍了西坡的景点详细请看链接:一个人的旅行,据说能看到长白山天池全凭运气,您的运气如何?今日介绍...