JDK8新特性
JDK8新特性
一、Lambda表达式:
Lambda表达式:
1、特殊的匿名内部类,语法更简介;
2、Lambda表达式允许把函数作为一个方法的参数(函数作为方法参数传递),将代码像数据一样传递;
Lambda引入了新的操作符:->(箭头操作符),->将表达式分成两部分
1、左侧:(参数1,参数2·····)表示参数列表
2、右侧:{}内部是方法体
~注意事项:
~形参列表的数据类型会自动推断
~如果形参列表为空,只需保留()
~如果形参只有一个,()可以省略,只需要参数的名称即可
~如果执行语句只有一句,且无返回值,{}可以省略,若有返回值,则若想省去{},则必须同时省略return,且执行语句也保证只有一句
Typora
二、函数式接口:
-
如果一个接口只有一个抽象方法,则该接口称为函数式接口,函数式接口可以使用Lambda表达式,Lambda表达式会被匹配到这个抽象方法上。
-
@Functionallnterface注解检测接口是否符合函数式接口
/** * Lambda表达式的使用 */ public class Demo1 { public static void main(String[] args) { //匿名内部类 Usb usb = new Usb() { @Override public void service() { System.out.println("鼠标开始工作了~~~~~~~~~~"); } }; //Lambda表达式 run(() -> System.out.println("鼠标开始工作了~~~~~~~~~~");); } public static void run(Usb usb) { usb.service(); } } /** * 函数时接口 */ @FunctionalInterface interface Usb { void service(); }
三、函数式接口使用:
Consumer消费型接口
Supplier供给型接口
Function函数型接口
predicate断言型接口
/**
* Lambda表达式的使用
*/
public class Demo1 {
public static void main(String[] args) {
//匿名内部类
Consumer<Double> consumer = new Consumer() {
@Override
public void accept(Object o) {
System.out.println("今晚李公子消费" + o);
}
};
happy(consumer, 1000.0);
//Lambda表达式(消费型接口)
happy(d -> System.out.println("今晚李公子消费" + d), 2000.0);
//Lambda表达式(供给型接口)
System.out.println(Arrays.toString(getNums(() -> new Random().nextInt(100), 5)));
//Lambda表达式(函数型接口)
System.out.println(handerString(a -> a.trim().toUpperCase(), " abc "));
//Lambda表达式(断言型接口)
List<String> list = new ArrayList(){{
add("张三");
add("李四");
add("王五");
add("张九");
}};
System.out.println(filterName(str -> str.startsWith("张"), list));
}
//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 < arr.length; i++) {
arr[i] = supplier.get();
}
return arr;
}
//Function函数型接口
public static String handerString(Function<String, String> function, String str) {
return function.apply(str);
}
//predicate断言型接口
public static List<String> filterName(Predicate<String> predicate, List<String> list){
List<String> resultList = new ArrayList<>();
for(String str : list){
if(predicate.test(str)){
resultList.add(str);
}
}
return resultList;
}
}
四、方法引用
方法引用是lambda表达式的一种简写形式。如果lambda表达式方法体中只有是调用一个特定的已经存在的方法,则可以使用方法引用
常见形式:
对象::实例方法
类::静态方法
类::实例方法
类::new
五、方法引用使用
/**
* Lambda表达式的使用
*/
public class Demo1 {
public static void main(String[] args) {
Consumer<String> consumer = s -> System.out.println(s);
//1、对象::实例方法
Consumer<String> consumer1 = System.out::print;
consumer1.accept("你好");
/////////////////////////////////////////////////////////////////////////
Comparator<Integer> comparator =(o1, o2) -> Integer.compare(o1, o2);
//2、类::静态方法
Comparator<Integer> comparator1 = Integer::compare;
System.out.println(comparator1.compare(2, 1));
/////////////////////////////////////////////////////////////////////////
Function<Employee, String> function = e -> e.getName();
//3、类::实例方法
Function<Employee, String> function1 = Employee::getName;
System.out.println(function.apply(new Employee("张三", 10.0)));
/////////////////////////////////////////////////////////////////////////
//4、类::new
Supplier<Employee> supplier = () -> new Employee("李四",18);
Supplier<Employee> supplier1 = Employee::new;
System.out.println(supplier1);
}
}
class Employee{
private String name;
private double money;
public Employee(String name, double money) {
this.name = name;
this.money = money;
}
@Override
public String toString() {
return "Employee{" +
"name='" + name + '\'' +
", money=" + money +
'}';
}
public Employee() {
}
public void setName(String name) {
this.name = name;
}
public void setMoney(double money) {
this.money = money;
}
public String getName() {
return name;
}
public double getMoney() {
return money;
}
}
六、Steram API
1、什么是Steram
流(Stream)中保存对集合或数组数据的操作。和集合类似,但集合中保存的是数据。
2、Stream特点
Stream自己不会存储元素
Stream不会改变源对象。相反,他们会返回一个持有结果的新Stream
Stream操作时延时的。这意味着他们会等到需要结果的时候才执行
3、Stream使用步骤
创建
新建一个流
中间操作
在一个或多个步骤中,将初始化Stream转化到另一个Stream的中间操作
终止操作
使用一个终止操作来产生一个结果。该操作会强制它之前的延迟操作立即执行。在这之后,该Stream就不能使用
4、创建Stream
通过Collection对象的stream()或parallelStream()方法
通过Arrays类的stream()方法
通过Stream接口的of(),iterate(),generate()方法
通过IntStream、LongStream、DoubleStream接口中的of、range、rangeClosed方法
/**
* Lambda表达式的使用
*/
public class Demo1 {
public static void main(String[] args) {
//1、通过Collection对象的stream()或parallelStream()方法
List<String> list = new ArrayList<>();
list.add("apple");
list.add("huawei");
list.add("xiaomi");
// Stream<String> stream = list.stream(); //串行流
Stream<String> stringStream = list.parallelStream(); //并行流
//遍历
// stream.forEach(s -> System.out.println(s));
stringStream.forEach(System.out::println);
//////////////////////////////////////////////////////////////////////////
//2、通过Arrays类的stream()方法
String[] arr = {"aaa","bbb","ccc","ddd"};
Stream<String> s = Arrays.stream(arr);
s.forEach(System.out::println);
//////////////////////////////////////////////////////////////////////////
//3、通过Stream接口的of(),iterate(),generate()方法
Stream<Integer> stream = Stream.of(10, 20, 30, 40, 50, 60);
stream.forEach(System.out::println);
//迭代流
System.out.print("--------------生成流---------------");
Stream<Integer> iterate = Stream.iterate(0, x -> x + 2);
iterate.limit(10).forEach(System.out::println);
//生成流
System.out.print("--------------生成流---------------");
Stream<Integer> generate = Stream.generate(() -> new Random().nextInt(100));
generate.limit(10).forEach(System.out::println);
//////////////////////////////////////////////////////////////////////////
//4、通过IntStream、LongStream、DoubleStream接口中的of、range、rangeClosed方法
System.out.print("--------------IntStream通过of---------------");
IntStream intStream = IntStream.of(100, 200, 300, 400);
intStream.forEach(System.out::println);
System.out.print("--------------IntStream通过range---------------");
IntStream range = IntStream.range(0, 10);
range.forEach((System.out::println));
System.out.print("--------------IntStream通过rangeClosed---------------");
IntStream rangeClosed = IntStream.rangeClosed(0, 10);
rangeClosed.forEach((System.out::println));
}
}
5、中间操作、终止操作
中间操作
filter、limit、skip、distinct、sorted
map
parallel
public class Demo1 {
public static void main(String[] args) {
List<Employee> list = new ArrayList<>();
list.add(new Employee("小王", 100));
list.add(new Employee("小张", 200));
list.add(new Employee("小李", 300));
list.add(new Employee("小孙", 400));
list.add(new Employee("小刘", 500));
list.add(new Employee("小王", 100));
//中间操作1
//1、filter 过滤
System.out.println("--------------filter 过滤-------------");
list.stream().filter(e -> e.getMoney() > 200).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(1).forEach(System.out::println);
//4、distinct 去重
System.out.println("--------------distinct 去重-------------");
list.stream().distinct().forEach(System.out::println);
//5、sorted 排序
System.out.println("--------------sorted 排序-------------");
list.stream().sorted((e1, e2) -> Integer.compare(e1.getMoney(), e2.getMoney())).forEach(System.out::println);
////////////////////////////////////////////////////////////////////////////////
//中间操作2
list.stream().map(e -> e.getName()).forEach(System.out::println);
///////////////////////////////////////////////////////////////////////////////
//中间操作3 采用paraller多线程效率高
List<String> integers = new ArrayList<>();
for (int i = 0; i < 5000000; i++) {
integers.add(UUID.randomUUID().toString());
}
//串行
long start = System.currentTimeMillis();
long count = integers.stream().sorted().count(); //串行
// long count = integers.parallelStream().sorted().count();//并行
System.out.print(count);
long end = System.currentTimeMillis();
System.out.println("串行用时:"+(end-start));
}
}
class Employee {
private String name;
private Integer money;
public Employee(String name, Integer money) {
this.name = name;
this.money = money;
}
public Employee() {
}
public String getName() {
return name;
}
public Integer getMoney() {
return money;
}
public void setName(String name) {
this.name = name;
}
public void setMoney(Integer money) {
this.money = money;
}
@Override
public String toString() {
return "Employee{" +
"name='" + name + '\'' +
", money=" + money +
'}';
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Employee employee = (Employee) o;
return name.equals(employee.name) &&
money.equals(employee.money);
}
@Override
public int hashCode() {
return Objects.hash(name, money);
}
}
终止操作
forEach、min、max、count
reduce、collect
public class Demo1 {
public static void main(String[] args) {
List<Employee> list = new ArrayList<>();
list.add(new Employee("小王", 100));
list.add(new Employee("小张", 200));
list.add(new Employee("小李", 300));
list.add(new Employee("小孙", 400));
list.add(new Employee("小刘", 500));
list.add(new Employee("小王", 100));
//终止操作foreach
list.stream().filter(e -> {
System.out.println("过滤了");
return e.getMoney()>100;
});
// .forEach(System.out::println);
////////////////////////////////////////////////
//终止操作reduce
Optional<Integer> reduce = list.stream().map(e -> e.getMoney()).reduce((x, y) -> x + y);
System.out.print(reduce);
//终止操作collect,将所有员工姓名封装成一个list
list.stream().map(e -> e.getName()).collect(Collectors.toList()).forEach(System.out::println);
}
}
class Employee {
private String name;
private Integer money;
public Employee(String name, Integer money) {
this.name = name;
this.money = money;
}
public Employee() {
}
public String getName() {
return name;
}
public Integer getMoney() {
return money;
}
public void setName(String name) {
this.name = name;
}
public void setMoney(Integer money) {
this.money = money;
}
@Override
public String toString() {
return "Employee{" +
"name='" + name + '\'' +
", money=" + money +
'}';
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Employee employee = (Employee) o;
return name.equals(employee.name) &&
money.equals(employee.money);
}
@Override
public int hashCode() {
return Objects.hash(name, money);
}
}
七、新时间API
1、以往时间API存在问题:
线程安全问题、设计混乱
public class Demo1 {
public static void main(String[] args) throws ExecutionException, InterruptedException {
//SimpleDateFormat线程不安全
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
//创建线程池
ExecutorService pool = Executors.newFixedThreadPool(10);
//SimpleDateFormat线程不安全需要同步代码块
Callable<Date> objectCallable = () -> {
synchronized (sdf) {
return sdf.parse("2020-04-25");
}
};
List<Future<Date>> list = new ArrayList<>();
//开启十个线程
for (int i = 0; i < 10; i++) {
Future<Date> submit = pool.submit(objectCallable);
list.add(submit);
}
//打印结果
for (Future<Date> future : list) {
System.out.println(future.get());
}
pool.shutdown();
/////////////////////////////////////////////////////////////////////
//新时间API:DateTimeFormatter、LocalDate线程安全
pool = Executors.newFixedThreadPool(10);
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd");
//SimpleDateFormat线程不需要需要同步代码块
Callable<LocalDate> localDateCallable = () -> LocalDate.parse("2020-04-25",dtf);
List<Future<LocalDate>> list1 = new ArrayList<>();
//开启十个线程
for (int i = 0; i < 10; i++) {
Future<LocalDate> submit = pool.submit(localDateCallable);
list1.add(submit);
}
//打印结果
for (Future future : list) {
System.out.println(future.get());
}
pool.shutdown();
}
}
2、本地化日期时间APl
LocalDate
LocalTime
LocalDateTime
public class Demo1 {
public static void main(String[] args) throws ExecutionException, InterruptedException {
//1、创建本地时间
LocalDateTime localDateTime = LocalDateTime.now();
//2、自定义时间
LocalDateTime of = LocalDateTime.of(2020, 10, 12, 9, 10);
System.out.println(localDateTime.getYear());
System.out.println(localDateTime.getMonthValue());
System.out.println(localDateTime.getDayOfMonth());
System.out.println(localDateTime.getDayOfMonth());
//3、添加两天
LocalDateTime localDateTime1 = localDateTime.plusDays(2);
System.out.println(localDateTime1);
//4、减少一个月
LocalDateTime localDateTime2 = localDateTime.minusMonths(1);
System.out.println(localDateTime2);
}
}
3、Instant:时间戳
//1、创建Instant,时间戳
Instant instant = Instant.now();
System.out.println(instant.toString());
System.out.println(instant.toEpochMilli());
System.out.println(System.currentTimeMillis() );
//2、添加减少时间
Instant instant1 = instant.plusSeconds(10);
System.out.println(Duration.between(instant, instant1).toMillis());
4、ZoneId:时区
//3、ZoneId
Set<String> availableZoneIds = ZoneId.getAvailableZoneIds();
for(String string : availableZoneIds){
System.out.println(string);
}
System.out.println(ZoneId.systemDefault().toString());
5、Date、Instant、LocalDateTime的转换
//1、Date -> Instant -> LocalDateTime
Date date = new Date();
Instant instant2 = date.toInstant();
System.out.println(instant2);
LocalDateTime localDateTime = LocalDateTime.ofInstant(instant2, ZoneId.systemDefault());
System.out.println(localDateTime);
//2、LocalDateTime -> Instant -> Date
Instant instant3 = localDateTime.atZone(ZoneId.systemDefault()).toInstant();
System.out.println(instant3);
Date from = Date.from(instant3);
System.out.println(from);
6、DateTimeFormatter:格式化类
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
//把时间转换成字符串
String format = dtf.format(LocalDateTime.now());
System.out.println(format);
//把字符串转换成时间
LocalDateTime parse = LocalDateTime.parse("2020-10-12 10:10:10", dtf);
System.out.println(parse);
八、总结
1、Lambda表达式:
允许把函数作为一个方法参数传递
2、函数式接口使用:
Consumer消费型接口
Supplier供给型接口
Function函数型接口
predicate断言型接口
3、Stream API
把对数据的操作封装成一个流
步骤:创建、中间操作、终止操作
浙公网安备 33010602011771号