荐 Java语言基础之JDK1.8新特性(Lambda表达式、函数式接口、Stream流、新的日期API)
Java8概述
是Java语言开发的一个主要版本。Oracle公司于2014年3月18日发布Java8版本。
- 支持Lambda表达式
- 函数式接口
- 新的Stream API
- 新的日期 API
- 其他特性
Lambda表达式
特殊的内部类,语法更加简洁。
lambda表达式允许把函数作为一个方法的参数(函数作为方法参数传递),将代码像数据一样传递。
基本语法
<函数式接口> <变量名> = (参数1, 参数2...)->{
//方法体
};
Lambda表达式引入了新的操作符:->(箭头操作符),->将表达式分成两部分
- 左侧:(参数1, 参数2…)
- 右侧:{} 内部是方法体
注意事项
- 形参列表的数据类型会自动判断
- 如果形参列表为空,只需保留()
- 如果形参只有1个,()可以省略,只需要参数的名称即可
- 如果方法体中只有一句代码,或者无返回值,{}可以省略,若有返回值,则若想去掉{},则必须同时省略return,且执行语句也保证只有一句
- Lambda表达式不会生成单独的内部类文件
代码演示1
package cn.itcast.demo;
public class LambdaDemo {
public static void main(String[] args) {
//匿名内部类
Runnable runnable = new Runnable() {
@Override
public void run() {
System.out.println("子线程1执行了........");
}
};
new Thread(runnable).start();
//使用lambda表达式,如果方法体中只有一行代码的话,可以将大括号省略掉
Runnable runnable2 = ()->System.out.println("子线程2执行了.......");
new Thread(runnable2).start();
//最简形式
new Thread(()->System.out.println("子线程3执行了.......")).start();
}
}
代码演示2
package cn.itcast.demo;
import java.util.Comparator;
import java.util.TreeSet;
public class LambdaDemo2 {
public static void main(String[] args) {
//匿名内部类
Comparator<String> com = new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
return o1.length() - o2.length();
}
};
TreeSet<String> ts = new TreeSet<String>(com);
//Lambda表达式
Comparator<String> com2 = (String o1, String o2)->{
return o1.length()-o2.length();
};
TreeSet<String> ts2 = new TreeSet<String>(com2);
Comparator<String> com3 = (o1, o2) -> o1.length()-o2.length();
TreeSet<String> ts3 = new TreeSet<String>(com3);
}
}
函数式接口
如果一个接口只有一个抽象方法,则该接口称之为函数式接口,函数式接口可以使用Lambda表达式,Lambda表达式会被匹配到这个抽象方法上。
那么如何判断一个接口是否是函数式接口呢?
可以使用这个注解
@FunctionalInterface 注解检测接口是否符合函数式接口
代码演示
package cn.itcast.demo;
//函数式接口
@FunctionalInterface
public interface Usb {
void service();
}
LambdaDemo3
package cn.itcast.demo;
public class LambdaDemo3 {
public static void main(String[] args) {
//匿名内部类
Usb mouse = new Usb() {
@Override
public void service() {
System.out.println("鼠标开始工作了........");
}
};
run(mouse);
//Lambda表达式
Usb fan = ()->System.out.println("风扇开始工作了.......");
run(fan);
}
public static void run(Usb usb){
usb.service();
}
}
常见的函数式接口
函数式接口 | 参数类型 | 返回类型 | 说明 |
---|---|---|---|
Consumer | T | void | void accept(T t); 对类型T的对象应用操作 |
Suppiler | 无 | T | T get(); 返回类型为T的对象 |
Function<T,R> | T | R | R apply(T t); 对类型为T的对象应用操作,并返回类型为R类型的对象 |
Predicate | T | boolean | boolean test(T t); 确定类型为T的对象是否满足条件,并返回boolean类型 |
除了表格中的这几个函数式接口,Runnable、Comparator等也属于函数式接口。
package cn.itcast.demo;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Random;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;
public class LambdaDemo4 {
public static void main(String[] args) {
//匿名内部类
Consumer<Double> consumer = new Consumer<Double>() {
@Override
public void accept(Double t) {
System.out.println("聚餐消费"+t);
}
};
happy(consumer, 1000);
//Lambda表达式
Consumer<Double> consumer2 = t->System.out.println("聚餐消费"+t);
happy(consumer2, 1200);
happy(t->System.out.println("唱歌消费"+t),2000);
System.out.println("--------------------------");
int[] arr = getNums(() -> new Random().nextInt(100), 5);
System.out.println(Arrays.toString(arr));
System.out.println("--------------------------");
String str = handlerString(s -> s.toUpperCase(), "hello");
System.out.println(str);
System.out.println("--------------------------");
List<String> names = new ArrayList<String>();
names.add("zhangsan");
names.add("zhangxiaohua");
names.add("lisi");
names.add("wangwu");
List<String> result = filterNames(s -> s.startsWith("zhang"), names);
System.out.println(result.toString());
List<String> result2 = filterNames(s -> s.length()>5, names);
System.out.println(result2.toString());
}
//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 str : list){
if(predicate.test(str)){
resultList.add(str);
}
}
return resultList;
}
}
运行结果
方法引用
方法引用是Lambda表达式的一种简写形式。如果Lambda表达式方法体中只是调用一个特定的已经存在的方法,则可以使用方法引用。
常见形式:
- 对象::实例方法
- 类::静态方法
- 类::实例方法
- 类::new
代码演示
package cn.itcast.demo;
import java.util.Comparator;
import java.util.function.Consumer;
//方法引用
public class LambdaDemo5 {
public static void main(String[] args) {
//对象::实例方法
Consumer<String> consumer = s->System.out.println(s);
consumer.accept("hello");
//使用方法引用
Consumer<String> consumer2 = System.out::println;
consumer2.accept("world");
//类::静态方法
Comparator<Integer> com = (o1, o2)->Integer.compare(o1, o2);
Comparator<Integer> com2 = Integer::compare;
//.....
}
}
流(Stream)
流中保存对集合或数组数据的操作。和集合类似,但是集合中保存的是数据,而流中保存的是操作。
Stream的特点
- Stream自己不会存储元素。
- Stream不会改变源对象,相反,他们会返回个持有结果的新Stream。
- Stream操作是延迟执行的。意味着他们会等到需要结果的时候才执行。
Stream的使用步骤
- 创建:新建一个流
- 中间操作:在一个或多个步骤中,将初始Stream转换到另一个Stream的中间操作。
- 终止操作:使用一个终止操作来产生一个结果,该操作会强制它之前的延迟操作立即执行,在这之后,该Stream就不能使用了。
创建Stream
- 通过Collection对象的stream()方法或parallelStream()方法
- 通过Arrays的stram()方法
- 通过Stream接口的of()、iterator()、generate()方法
代码演示
package cn.itcast.demo2;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Random;
import java.util.stream.Stream;
public class StreamDemo {
public static void main(String[] args) {
//通过Collection对象的stream()方法或parallelStream()方法
ArrayList<String> al = new ArrayList<String>();
al.add("apple");
al.add("huawei");
al.add("xiaomi");
Stream<String> stream = al.stream();
//遍历
stream.forEach(s->System.out.println(s));
System.out.println("----------------------");
//通过Arrays的stram()方法
String[] arr = {"aaa", "bbb", "ccc"};
Stream<String> stream2 = Arrays.stream(arr);
stream2.forEach(s->System.out.println(s));
System.out.println("----------------------");
//通过Stream接口的of()、iterator()、generate()方法
Stream<Integer> stream3 = Stream.of(10, 20, 30, 40);
stream3.forEach(System.out::println);
System.out.println("-----------迭代流-----------");
Stream<Integer> iterate = Stream.iterate(0, x -> x + 2);
iterate.limit(10).forEach(System.out::println);
System.out.println("-----------生成流-----------");
Stream<Integer> generate = Stream.generate(() -> new Random().nextInt(100));
generate.limit(10).forEach(System.out::println);
}
}
中间操作
- filter、limit、skip、distinct、sorted
- map
- parallel
代码演示
package cn.itcast.demo2;
import java.util.ArrayList;
public class StreamDemo2 {
public static void main(String[] args) {
ArrayList<Student> al = new ArrayList<Student>();
al.add(new Student("zhangsan",8000));
al.add(new Student("lisi",12000));
al.add(new Student("wangwu",25000));
al.add(new Student("zhouqi",5000));
al.add(new Student("zhouqi",5000));
//中间操作1
//filter 过滤
System.out.println("----------filter---------");
al.stream().filter(stu->stu.getSalary()>10000).forEach(System.out::println);
//limit 限制
System.out.println("----------limit---------");
al.stream().limit(2).forEach(System.out::println);
//skip 跳过
System.out.println("----------skip---------");
al.stream().skip(2).forEach(System.out::println);
//distinct 去重复
System.out.println("----------distinct---------");
al.stream().distinct().forEach(System.out::println);
//sorted 排序
al.stream().sorted((stu1,stu2)->Double.compare(stu1.getSalary(),stu2.getSalary()))
.forEach(System.out::println);
//中间操作2 map
System.out.println("----------map---------");
al.stream().map(stu->stu.getName()).forEach(System.out::println);
//中间操作3 parallel 采用多线程效率
System.out.println("----------parallel---------");
al.parallelStream().forEach(System.out::println);
}
}
串行流和并行流的区别
package cn.itcast.demo2;
import java.util.ArrayList;
import java.util.UUID;
public class StreamTest {
public static void main(String[] args) {
//串行流和并行流的区别
ArrayList<String> list = new ArrayList<String>();
for(int i = 0; i < 5000000; i++){
list.add(UUID.randomUUID().toString());
}
//并行流 10s 并行
long start = System.currentTimeMillis();
long count = list.parallelStream().sorted().count();
System.out.println(count);
long end = System.currentTimeMillis();
System.out.println("用时:"+(start-end));
}
}
终止操作
- forEach、min、max、count
- reduce、collect
代码演示
package cn.itcast.demo2;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
public class StreamDemo3 {
public static void main(String[] args) {
ArrayList<Student> al = new ArrayList<Student>();
al.add(new Student("zhangsan",8000));
al.add(new Student("lisi",12000));
al.add(new Student("wangwu",25000));
al.add(new Student("zhouqi",5000));
al.add(new Student("zhouqi",5000));
//终止操作 forEach
al.stream().filter(e->{
System.out.println("过滤了......");
return e.getSalary()>10000;
}).forEach(System.out::println);
//min max count
System.out.println("---------min---------");
Optional<Student> min = al.stream()
.min((stu1, stu2) -> Double.compare(stu1.getSalary(), stu2.getSalary()));
System.out.println(min.get());
System.out.println("---------max---------");
Optional<Student> max = al.stream()
.min((stu1, stu2) -> Double.compare(stu1.getSalary(), stu2.getSalary()));
System.out.println(max.get());
System.out.println("---------count---------");
long count = al.stream().count();
System.out.println("学生人数:"+count);
//终止操作 reduce 规约
//计算所有工资
System.out.println("---------reduce---------");
Optional<Double> sum = al.stream().map(stu -> stu.getSalary()).reduce((x, y) -> x + y);
System.out.println(sum.get());
//终止操作 collect 收集
//获取所有学生姓名,封装一个list集合
System.out.println("---------collect---------");
List<String> names = al.stream().map(stu -> stu.getName()).collect(Collectors.toList());
for(String name : names){
System.out.println(name);
}
}
}
新的日期 API
之前的日期API存在问题:线程安全问题、设计混乱
演示线程安全问题
package cn.itcast.demo3;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.*;
//演示线程安全问题
public class DateDemo {
public static void main(String[] args) throws ExecutionException, InterruptedException {
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
ExecutorService pool = Executors.newFixedThreadPool(10);
Callable<Date> callable = new Callable<Date>() {
@Override
public Date call() throws Exception {
return sdf.parse("20200425");
}
};
List<Future<Date>> list = new ArrayList<>();
for(int i = 0; i < 10; i++){
Future<Date> future = pool.submit(callable);
list.add(future);
}
for(Future<Date> future : list){
System.out.println(future.get());
}
pool.shutdown();
}
}
本地化时间 API
- LocalDate
- LocatTime
- LocalDateTime
- Instant:时间戳
- ZoneId:时区
代码演示
package cn.itcast.demo3;
import java.time.LocalDateTime;
public class LocalDateTimeDemo {
public static void main(String[] args) {
//创建本地时间
LocalDateTime ldt = LocalDateTime.now();
System.out.println(ldt);
System.out.println(ldt.getYear());
System.out.println(ldt.getMonthValue());
System.out.println(ldt.getDayOfMonth());
//添加两天
LocalDateTime newDate = ldt.plusDays(2);
System.out.println(newDate);
//减少一个月
LocalDateTime newDate2 = ldt.minusMinutes(1);
System.out.println(newDate2);
}
}
代码演示2
package cn.itcast.demo3;
import java.time.Duration;
import java.time.Instant;
import java.time.ZoneId;
import java.util.Set;
public class InstantDemo {
public static void main(String[] args) {
//创建
Instant instant = Instant.now();
System.out.println(instant.toString());
System.out.println(instant.toEpochMilli());
System.out.println(System.currentTimeMillis());
//添加、减少时间
Instant instant2 = instant.plusSeconds(10);
System.out.println(Duration.between(instant, instant2).toMillis());
//3.ZoneId 时区
Set<String> availableZoneIds = ZoneId.getAvailableZoneIds();
for(String str : availableZoneIds){
System.out.println(str);
}
}
}
Date、Instant、LocalDateTime的转换
package cn.itcast.demo3;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Date;
public class TranferDemo {
public static void main(String[] args) {
//Date--->Instant--->LocalDateTime
Date date = new Date();
Instant instant = date.toInstant();
System.out.println(instant);
LocalDateTime localDateTime = LocalDateTime.ofInstant(instant, ZoneId.systemDefault());
System.out.println(localDateTime);
System.out.println("----------------------------");
//LocalDateTime--->Instant--->Date
Instant instant2 = localDateTime.atZone(ZoneId.systemDefault()).toInstant();
System.out.println(instant2);
Date date2 = Date.from(instant2);
System.out.println(date2);
}
}
DateTimeFormatter:格式化类
package cn.itcast.demo3;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
public class DataTimeFormatterDemo {
public static void main(String[] args) {
//创建DateTimeFormatter对象
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss");
//格式化时间字符串
String format = dtf.format(LocalDateTime.now());
System.out.println(format);
//将字符串解析成时间
LocalDateTime localDateTime = LocalDateTime.parse("2020-03-01 10:20:35", dtf);
System.out.println(localDateTime);
}
}
本文地址:https://blog.csdn.net/weixin_45620489/article/details/107287417
上一篇: 荐 MATLAB 像素画绘制APP
下一篇: 完整的访问统计系统(一:数据库篇)