## 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
把對資料的操作封裝成一個流
步驟:建立、中間操作、終止操作