Java 8 新增的特性:
- Lambda表达式。
- 函数式接口
- 方法引用与构造器引用
- Stream API
- 接口中默认方法与静态方法
- 新时间日期API
- 其他新的特性
一、Lamnda表达式
package com.lzw.demo2;
public class LambdaDemo {
public static void main(String[] args) {
LambdaDemo tester = new LambdaDemo();
// 类型声明
MathTest addition = (int a, int b) -> a + b;
// 不用类型声明
MathTest subtraction = (a, b) -> a - b;
// 大括号中的返回语句
MathTest multiplication = (int a, int b) -> {
return a * b;
};
// 没有大括号及返回语句
MathTest division = (int a, int b) -> a / b;
System.out.println("10 + 5 = " + tester.test(10, 5, addition));
System.out.println("10 - 5 = " + tester.test(10, 5, subtraction));
System.out.println("10 x 5 = " + tester.test(10, 5, multiplication));
System.out.println("10 / 5 = " + tester.test(10, 5, division));
// 不用括号
GreetingService greetService1 = message -> System.out.println("Hello " + message);
// 用括号
GreetingService greetService2 = (message) -> System.out.println("Hello " + message);
greetService1.sayMessage("Runoob");
greetService2.sayMessage("Google");
}
interface MathTest {
int test(int a, int b);
}
interface GreetingService {
void sayMessage(String message);
}
private int test(int a, int b, MathTest mathTest){
return mathTest.test(a, b);
}
输出打印:
10 + 5 = 15
10 - 5 = 5
10 x 5 = 50
10 / 5 = 2
Hello Runoob
Hello Google
特性:
可选类型声明:不需要声明参数类型,编译器可以统一识别参数值。
可选的参数圆括号:一个参数无需定义圆括号,但多个参数需要定义圆括号。
可选的大括号:如果主体包含了一个语句,就不需要使用大括号。
可选的返回关键字:如果主体只有一个表达式返回值则编译器会自动返回值,大括号需要指定明表达式返回了一个数值。
二、函数式接口
函数式接口(Functional Interface)就是一个有且仅有一个抽象方法,但是可以有多个非抽象方法的接口。
四大内置接口:
Consumer<T>:消费型接口(void accept(T t))
Supplier<T>:供给型接口(T get())
Function<T, R>:函数型接口(R apply(T t))
Predicate<T>:断言型接口(boolean test(T t))
例如:
package com.lzw.demo2;
import java.util.ArrayList;
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 Test {
public static void main(String[] args) {
//消费型
consumo(300, (x) -> System.out.println(x));
//供给型接口
Random ran = new Random();
List<Integer> list = supplier(5, () -> ran.nextInt(24));
for (Integer i : list) {
System.out.println(i);
}
//函数型接口
String function = function(" ba csd ", x -> x.trim());
System.out.println(function);
//断言型接口
List<Integer> list1 = new ArrayList<>();
list1.add(1);
list1.add(4);
list1.add(6);
list1.add(9);
List<Integer> filterInt = filterInt(list1, x -> (x<5));
for (Integer integer : filterInt) {
System.out.println(integer);
}
}
public static void consumo(double money, Consumer<Double> c) {
c.accept(money);
}
public static List<Integer> supplier(int sum, Supplier<Integer> sup) {
List<Integer> list = new ArrayList<Integer>();
for (int i = 0; i < sum; i++) {
list.add(sup.get());
}
return list;
}
public static String function(String str, Function<String, String> fun){
return fun.apply(str);
}
public static List<Integer> filterInt(List<Integer> list,Predicate<Integer> pre){
List<Integer> list2 = new ArrayList<>();
for (Integer integer : list) {
if (pre.test(integer))
list2.add(integer);
}
return list2;
}
}
三、方法引用与构造器引用
四、Stream API
java 8中创建流的两种方式:
1、stream() − 为集合创建串行流。
2、parallelStream() − 为集合创建并行流。
public static void main(String[] args) {
List<String> strings = Arrays.asList("a", "", "c", "g", "d","", "j");
Stream<String> stream = strings.stream();
Stream<String> stream2 = strings.parallelStream();
List<String> filtered = strings.stream().filter(string -> !string.isEmpty()).collect(Collectors.toList());
System.out.println(filtered);
}
1、Stream 提供了新的方法 'forEach' 来迭代流中的每个数据。
2、map 方法用于映射每个元素到对应的结果。
3、filter 方法用于通过设置的条件过滤出元素。
4、limit 方法用于获取指定数量的流。
5、sorted 方法用于对流进行排序。
当然还有很多,这里就不一一举例了。
public static void main(String[] args) {
Random random = new Random();
random.ints().limit(10).forEach(System.out::println);
random.ints().limit(10).sorted().forEach(System.out::println);
List<Integer> numbers = Arrays.asList(3, 2, 2, 3, 7, 3, 5);
List<Integer> squaresList = numbers.stream().map( i -> i*i).distinct().collect(Collectors.toList());
System.out.println(squaresList);
List<String>strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl");
int count = (int) strings.stream().filter(string -> string.isEmpty()).count();
System.out.println(count);
}
五、接口中默认方法与静态方法
为什么要有这个特性?
原来的接口优点是:面向抽象而不是面向具体编程;缺点是:需要修改接口时,就要修改全部实现该接口的类,相当的复杂。引入默认接口就可以解决接口的修改与现有的实现不兼容的问题。
格式:
修改默认方法的两种方式:覆盖重写接口的默认方法;使用 super 来调用指定接口的默认方法
package com.lzw.test;
/**
* @author lzw
* @Date 2019年7月9日
*/
public class SuperMan2 implements Teacher2, Chengxuyuan2 {
// 使用 super 来调用指定接口的默认方法:
public void test() {
Chengxuyuan2.super.test();
Teacher2.super.test();
}
public static void main(String[] args) {
new SuperMan2().test();
}
}
interface Chengxuyuan2 {
default void test() {
System.out.println("我是一个程序员!");
}
}
interface Teacher2 {
default void test() {
System.out.println("我是一个老师!");
}
}
静态方法:
package com.lzw.test;
/**
* @author lzw
* @Date 2019年7月9日
*/
public class SuperMan implements Teacher, Chengxuyuan {
public void test() {
Chengxuyuan.super.test();
Teacher.super.test();
Chengxuyuan.blowHorn();
System.out.println("我是一个程序员老师呀!");
}
public static void main(String[] args) {
new SuperMan().test();
}
}
interface Chengxuyuan {
default void test() {
System.out.println("我是一个程序员!");
}
// 静态方法
static void blowHorn() {
System.out.println("搬砖中!!!");
}
}
interface Teacher {
default void test() {
System.out.println("我是一个老师!");
}
}
六、新时间日期API
直接上代码吧
package com.lzw.test;
import java.time.DayOfWeek;
import java.time.Duration;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.Month;
import java.time.Period;
import java.time.temporal.TemporalAdjusters;
public class Test {
public static void main(String[] args) throws InterruptedException {
/************************** 时间日期相关的类 ****************************/
// 获取当前的日期时间
LocalDateTime currentTime = LocalDateTime.now();
System.out.println("当前时间: " + currentTime);
// 当前日期 2019-07-09
LocalDate date1 = currentTime.toLocalDate();
System.out.println("date1: " + date1);
int month = currentTime.getMonth().getValue();
int day = currentTime.getDayOfMonth();
int hour = currentTime.getHour();
int minute = currentTime.getMinute();
int seconds = currentTime.getSecond();
System.out.println("月: " + month + ", 日: " + day + ", 时: " + hour + ", 分: " + minute + ", 秒: " + seconds);
// 2012年本月的第十天的当前时间
LocalDateTime date2 = currentTime.withDayOfMonth(10).withYear(2012);
System.out.println("date2: " + date2);
// 2014-12-12
LocalDate date3 = LocalDate.of(2014, Month.DECEMBER, 12);
System.out.println("date3: " + date3);
// 22 小时 15 分钟
LocalTime date4 = LocalTime.of(22, 15);
System.out.println("date4: " + date4);
// 解析字符串
LocalTime date5 = LocalTime.parse("23:15:30");
System.out.println("date5: " + date5);
/********************** 计算两个日期或时间的差 *****************************/
// 计算两个日期之间的时间差
LocalTime lt1 = LocalTime.now();
Thread.sleep(1000);
LocalTime lt2 = LocalTime.now();
Duration duration2 = Duration.between(lt1, lt2);
System.out.println("1、相差:" + duration2.toMillis() + "秒");
// 计算两个日期之间的时间差
LocalDate ld1 = LocalDate.of(2013, 5, 1);
LocalDate ld2 = LocalDate.now();
Period period = Period.between(ld1, ld2);
System.out
.println("2、相差 : " + period.getYears() + " 年 " + period.getMonths() + " 月 " + period.getDays() + " 日");
/***************
* 日期的操纵 :TemporalAdjuster 和 TemporalAdjusters
***************/
// TemporalAdjuster:时间校正器
LocalDateTime ldt = LocalDateTime.now();
System.out.println(ldt);
// 将月中的天指定为10号
LocalDateTime ldt1 = ldt.withDayOfMonth(10);
System.out.println(ldt1);
// ldt2时间的下一个周日是什么时候
LocalDateTime ldt2 = LocalDateTime.now();
LocalDateTime ldt3 = ldt2.with(TemporalAdjusters.next(DayOfWeek.SUNDAY));
System.out.println(ldt3);
}
}
有空了继续补充