一、支持 lambda 表達式
例如:查詢學生信息,並打印
List<Student> studentList = Student.findAllStudent(); for(Student student:studentList){ System.out.println(student); }
使用 Lambda 的寫法
Student.findAllStudent().stream().forEach(e->System.out.println(e));
Student.findAllStudent().forEach(e->System.out.println(e));
例如:創建一個線程
Runnable runnable = new Runnable() { @Override public void run() { System.out.println(Thread.currentThread().getName()+":重寫run 方法"); } }; Thread t1 = new Thread(runnable,"t1"); t1.start();
使用 Lambda 的寫法:
new Thread(()->System.out.println(Thread.currentThread().getName()+":重寫run 方法"),"t2").start();
使用 Lambda 的前提:必須滿足是函數式接口,Runnable 就是一個函數式接口,用@FunctionalInterface 申明
此外: Java8 提供了模板函數式的接口在包: Java.util.function
01. 消費者接口
02.函數接口
03.判斷接口
04.提供者接口
除了上述接口,Java 就有的函數式接口Runnabkle Callable Comparator
Lambda中使用的變量必須顯示的聲明為 final
方法引用:
Student.findAllStudent().stream().forEach(System.out::println);
例如:
(Student s)->s.getSex();
Student::getSex
例如:輸出所有學生的姓名
Student.findAllStudent().stream().map(Student::getName).forEach(System.out::println);
復合函數:
Function<Integer,Integer> f = x->x+4; Function<Integer,Integer> g = x->x*2; Function<Integer,Integer> k = f.andThen(g); System.out.println(k.apply(2));
解析:先將輸入 +4 ,將得到的結果 *2 ,組合使用函數
二、引入流
流在 java.util.stream.Stream,支持數據處理操作的源生成的元素序列。
filter :接收Lambda,從流中排除某些元素
map: 接受一個lambda,將元素轉換成其他形式或者提取信息
limit: 截斷流,使元素不超過指定數量
collect: 將流轉換為其他形式
例如:查詢並打印年齡大於20的學生信息
List<Student> students = Student.findAllStudent(); List<Student> res = new ArrayList<>(); for(Student student :students){ if(student.getAge()>20){ res.add(student); } } for(Student student: res){ System.out.println(student); }
使用流:
Student.findAllStudent().stream() .filter(e->e.getAge()>20) .forEach(System.out::println);
例如:查詢所有北京的學生,並按年齡升序輸出
Student.findAllStudent().stream() .filter(e->e.getAddress().equals("北京")) .sorted(Comparator.comparing(Student::getAge)) .forEach(System.out::println);
內部迭代與外部迭代:
for-each 結構是一個語法糖,背后的是 Iterator 還丑陋的東西。
流可以分為:中間操作、終端操作
中間操作: filter 、 sorted 等會返回另一個流。{filter、map、limit、sorted、distinct}
終端操作:終端操作會從流的流水線生成結果,結果不是流的值。 void 、list 等結果.{forEach、count、collect}
例如:查詢集合中的偶數,去重復
List<Integer> numbers = Arrays.asList(10,12,2,12,10,1,2); numbers.stream() .filter(e->e%2==0) .distinct() .forEach(System.out::println);
例如:查詢集合中前 3 個數據
numbers.stream() .limit(3) .forEach(System.out::println);
例如:忽略集合中前3個數據
numbers.stream() .skip(3) .forEach(System.out::println);
例如:查詢學生信息中地址,去重
Student.findAllStudent().stream() .map(e->e.getAddress()) .distinct() .forEach(System.out::println);
例如:將【“Hello”,“World”】 處理為:【“H”,"e","l","o"...】
List<String> str = Arrays.asList("Hello","World"); List<String[]> res = str.stream() .map(e->e.split("")) .distinct() .collect(toList());
返回的是2個String 數組,而想要的結果是一個string 數組
List<String> res = str.stream() .map(e->e.split("")) .flatMap(Arrays::stream) .distinct() .collect(toList()); System.out.println(res);
flatMap : 把流中的每個值都換成另一個流,然后把所有的流連接起來形成一個流。
例如:判斷學生中是否所有的年齡都小於20
boolean res =Student.findAllStudent().stream() .allMatch(e->e.getAge()<20); System.out.println(res);
例如:判斷學生中是否有成都的
boolean res =Student.findAllStudent().stream() .anyMatch(e->e.getAddress()=="成都"); System.out.println(res);
規約:求學生的年齡和
int sum = Student.findAllStudent().stream() .map(Student::getAge) .reduce(0,(e1,e2)->e1+e2); System.out.println(sum);
int sum = Student.findAllStudent().stream() .map(Student::getAge) .reduce(0,Integer::sum); System.out.println(sum);
無初始值-規約:
Optional<Integer> sum = Student.findAllStudent().stream() .map(Student::getAge) .reduce((e1,e2)->e1+e2); System.out.println(sum);
例如:返回所有學生姓名字符串,按字母順序排列
String str = Student.findAllStudent().stream() .map(Student::getName) .distinct() .sorted() .reduce("",(e1,e2)->e1+e2); System.out.println(str);
例如:查找年齡最小的學習年齡
Optional<Integer> min = Student.findAllStudent().stream()
.map(Student::getAge)
.reduce(Integer::min);
System.out.println(min);
使用 groupingBy 按城市分組查詢:
Map<String,List<Student>> map = Student.findAllStudent().stream() .collect(groupingBy(Student::getAddress)); for(Map.Entry<String,List<Student>> entry: map.entrySet()){ System.out.println(entry.getKey()+","+entry.getValue()); }
收集器的 Joining 匯總
joining 會把流中每一個對象應用 toString 方法得到的字符串連接成一個字符串。
例如:將城市去重以字符串返回
String str = Student.findAllStudent().stream()
.map(Student::getAddress)
.distinct()
.collect(joining());
System.out.println(str);
String str = Student.findAllStudent().stream() .map(Student::getAddress) .distinct() .collect(joining(",")); System.out.println(str);
例如:將學生按年齡分組
Map<Integer,List<Student>> map = Student.findAllStudent().stream() .collect(groupingBy(Student::getAge)); for(Map.Entry<Integer,List<Student>> entry:map.entrySet()){ System.out.println(entry.getKey()+","+entry.getValue()); }
使用 counting
計算每個年齡組人的個數
Map<Integer,Long> map = Student.findAllStudent().stream() .collect(groupingBy(Student::getAge,counting())); for(Map.Entry<Integer,Long> entry:map.entrySet()){ System.out.println(entry.getKey()+","+entry.getValue()); }
並行流
使用 parallelStream 方法把集合轉換為並行流
打印學生信息
Student.findAllStudent().parallelStream().forEach(System.out::println);
輸出學生姓名
String str = Student.findAllStudent().parallelStream() .map(Student::getName) .collect(joining(",")); System.out.println(str);
分支/合並框架(ForkJoinPool)
目的:以遞歸方式將可以並行的任務拆分成更小的任務,然后將每個子任務的結果合並起來生成整體的結果
繼承 RecursiveTask<T>
Spliterator : 可分迭代器,可並行遍歷數據源中的數據
三、默認方法
問題:接口中的方法,子類必須實現。由於 java8 接口增加許多,為了不帶來更多的問題,添加新的機制
1.java8 允許在接口內聲明靜態方法
2.java8 引入一個新的功能 ,默認方法。接口能夠提供具體的實現
四、Optional 取代 null
java.util.Optional<T>
當變量存在時,Optional 對對象簡單的封裝,當變量不存在時,缺失的值被建模成 kong 的optional 對象。由 Optional.empty() 返回
五、CompleteableFuture 組合式異步編程
Future 接口,java5引入。提供了異步操作。
六、新的日期與時間 API
java.util.Date 、 java.utlo.Calender 設計的缺陷
缺陷: java.util.Date 無法表示日期,只能以毫秒精確時間。年份的起始選擇的是 1900 年,月份從 0 開始。
缺陷:java.util.Calendar 月份呢依然是從 0開始,取消 1900 年開始。
新的時間: java.time 包
1.獲取當前日期
LocalDate today = LocalDate.now();
System.out.println(today);
2.獲取指定日期
LocalDate localDate = LocalDate.of(2018,4,5);
System.out.println(localDate.getDayOfWeek());
System.out.println(localDate.getDayOfMonth());
System.out.println(localDate.getDayOfYear());
3.指定時間
LocalTime localTime = LocalTime.of(13,14,50);
System.out.println(localTime.getHour());
System.out.println(localTime.getMinute());
System.out.println(localTime.getSecond());