1.Lamda表達式
Lambda表達式的作用主要是用來簡化接口的創(chuàng)建摊滔,使用Lambda表達式接口必須是函數(shù)式接口
- 語法格式一:無參,無返回值店乐,Lambda體只需一條語句
- 語法格式二:Lambda只需要一個參數(shù)時艰躺,參數(shù)的小括號可以省略
- 語法格式三:當Lambda體只有一條語句時,return與大括號可以省略
- 語法格式四:參數(shù)的數(shù)據(jù)類型可以省略
@Test
public void testLambda() {
new Thread(() -> {
for (int i = 0; i < 10; i++) {
log.info(" {} ", i);
}
}).start();
}
2.函數(shù)式接口
函數(shù)式接口只能有一個抽象方法眨八,使用@FunctionalInterface注解可以檢查是否是函數(shù)式接口
- 自定義函數(shù)式接口
@FunctionalInterface
interface MyFunc<T> {
T getValue(T t);
}
- 四大內(nèi)置核心函數(shù)式接口
Consumner<T> : 消費型接口
void accept(T t);
用途:對類型為T的對象應(yīng)用操作腺兴,包含方法:void accept(T t);
@Test
public void testConsume() {
pay(1000, money -> System.out.println("購物消費了" + money + "元"));
}
private void pay(int money, Consumer<Integer> consumer) {
consumer.accept(money);
}
Supplier<T> :供給型接口
T get();
用途:返回類型為T的對象,包含方法:T get();
@Test
public void testSupplier() {
List<Integer> list = getNumList(10, () -> (int)(Math.random() * 100));
for (int num : list) {
System.out.println("supplier" + num);
}
}
private List<Integer> getNumList(int num, Supplier<Integer> supplier) {
List<Integer> list = new ArrayList<>();
for (int i = 0; i < num; i++) {
list.add(supplier.get());
}
return list;
}
Function<T , R>:函數(shù)式接口
R apply(T t);
用途:對類型為T的對象應(yīng)用操作廉侧,并返回結(jié)果页响,結(jié)果是R類型的對象,包含方法:R apply(T t);
@Test
public void testFunction() {
String name = "Jack Yang";
System.out.print(strHandler(name, String::toLowerCase));
}
private String strHandler(String str, Function<String, String> func) {
return func.apply(str);
}
Predicate<T>:斷言型接口
boolean test(T t);
用途:確定類型為T的對象是否滿足某約束段誊,并返回boolean值闰蚕,包含方法:boolean test(T t);
@Test
public void testPredicate() {
List<String> list = filterStr(
Arrays.asList("jackyang", "jackie", "jordan", "ronaldo", "figo", "zidane"),
s -> s.length() >= 6
);
for (String name : list) {
System.out.println(name);
}
}
private List<String> filterStr(List<String> list, Predicate<String> predicate) {
List<String> handleList = new ArrayList<>();
for(String str : list) {
if(predicate.test(str)) {
handleList.add(str);
}
}
return handleList;
}
其他函數(shù)式接口(http://www.runoob.com/java/java8-functional-interfaces.html)
3.方法引用
方法引用所引用的方法的參數(shù)列表與返回值類型,需要與函數(shù)式接口中抽象方法的參數(shù)列表和返回值類型保持一致
若Lambda 的參數(shù)列表的第一個參數(shù)枕扫,是實例方法的調(diào)用者陪腌,第二個參數(shù)(或無參)是實例方法的參數(shù)時,格式: ClassName::MethodName
構(gòu)造器的參數(shù)列表烟瞧,需要與函數(shù)式接口中參數(shù)列表保持一致
三種語法格式
- 對象::實例方法
- 類::靜態(tài)方法
- 類::實例方法
4.Stream API
集合講的是數(shù)據(jù)诗鸭,流講的是計算!
- Stream 自己不會存儲元素。
- Stream 不會改變源對象参滴。相反强岸,他們會返回一個持有結(jié)果的新Stream。
- Stream 操作是延遲執(zhí)行的砾赔。這意味著他們會等到需要結(jié)果的時候才執(zhí)行蝌箍。
Stream流的操作三個步驟
- 創(chuàng)建流(數(shù)據(jù)源:集合、數(shù)組)
- 中間操作(操作鏈暴心,對數(shù)據(jù)源數(shù)據(jù)進行計算)
- 終止操作(產(chǎn)生結(jié)果)
創(chuàng)建Stream流
- 集合創(chuàng)建流(Collection 接口擴展)
default Stream<E> stream() : 返回一個順序流
default Stream<E> parallelStream() : 返回一個并行流
- 數(shù)組創(chuàng)建流(Arrays 靜態(tài)方法)
static <T> Stream<T> stream(T[] array): 返回一個流
- 值創(chuàng)建流(靜態(tài)方法 Stream.of())
public static<T> Stream<T> of(T... values) : 返回一個流
- 創(chuàng)建無限流(函數(shù)創(chuàng)建 iterate和generate)
迭代 public static<T> Stream<T> iterate(final T seed, final UnaryOperator<T> f)
生成 public static<T> Stream<T> generate(Supplier<T> s)
@Slf4j
public class StreamTest extends AdminApiApplicationTests {
@Data
class Student {
private String name;
private Integer age;
public Student(String name, Integer age) {
this.name = name;
this.age = age;
}
}
@Test
public void testStreamCreate() {
System.out.println("-----------集合創(chuàng)建流-----------");
Arrays.asList("jackyang", "", "jordan", "helloworld", "hellokitty").stream().filter(s -> s.length() > 8).forEach(System.out::println);
System.out.println("-----------數(shù)據(jù)創(chuàng)建流-----------");
Student[] students = new Student[]{
new Student("jackyang", 30),
new Student("jordan", 40),
new Student("kitty", 18)
};
Arrays.stream(students).filter(student -> student.age > 20).forEach(System.out::println);
System.out.println("-----------值創(chuàng)建流-----------");
Stream.of(students).filter(student -> student.age < 20).forEach(System.out::println);
System.out.println("-----------創(chuàng)建無限流-----------");
Stream.iterate(5, s -> s + 2).limit(10).forEach(System.out::println);
Stream.generate(() -> (int)(Math.random() * 100)).limit(10).forEach(System.out::println);
}
}
中間操作
中間操作不會執(zhí)行任何的操作妓盲,而是在終止操作時一次性全部處理,稱為“惰性求值”
- filter(Predicate p) 接收 Lambda 從流中排除某些元素
- distinct() 通過流所生成元素的 hashCode() 和 equals() 去 除重復(fù)元素
- limit(long maxSize) 截斷流专普,使其元素不超過給定數(shù)量
- skip(long n) 跳過元素悯衬,返回一個剔除了前 n 個元素的流,若流中元素不足n個檀夹,則返回一個空流
- map(Function f) 接收一個函數(shù)作為參數(shù)筋粗,該函數(shù)會被應(yīng)用到每個元素上,并將其映射成一個新的元素炸渡。
- mapToDouble(ToDoubleFunction f) 接收一個函數(shù)作為參數(shù)娜亿,該函數(shù)會被應(yīng)用到每個元 素上,產(chǎn)生一個新的 DoubleStream
- mapToInt(ToIntFunction f) 接收一個函數(shù)作為參數(shù)蚌堵,該函數(shù)會被應(yīng)用到每個元 素上买决,產(chǎn)生一個新的 IntStream
- mapToLong(ToLongFunction f) 接收一個函數(shù)作為參數(shù),該函數(shù)會被應(yīng)用到每個元 素上吼畏,產(chǎn)生一個新的 LongStream
- flatMap(Function f) 接收一個函數(shù)作為參數(shù)督赤,將流中的每個值都換成另一個流,然后把所有流連接成一個流
- sorted() 產(chǎn)生一個新流宫仗,其中按自然順序排序
- sorted(Comparator comp) 產(chǎn)生一個新流够挂,其中按比較器順序排序
終止操作
終止操作會從流的流水線生成結(jié)果,其結(jié)果可以是任何不是流的值藕夫,例如:List孽糖、Integer,甚至是 void
匹配
- allMatch(Predicate p) 檢查是否匹配所有元素
- anyMatch(Predicate p) 檢查是否至少匹配一個元素
- noneMatch(Predicate p) 檢查是否沒有匹配所有元素
查找
- findFirst() 返回第一個元素
- findAny() 返回當前流中的任意元素
- count() 返回流中元素總數(shù)
- max(Comparator c) 返回流中最大值
- min(Comparator c) 返回流中最小值
遍歷
- forEach(Consumer c) 內(nèi)部迭代
規(guī)約
- reduce(T iden, BinaryOperator b) 可以將流中元素反復(fù)結(jié)合起來毅贮,得到一個值办悟,返回 T
- reduce(BinaryOperator b) 可以將流中元素反復(fù)結(jié)合起來,得到一個值滩褥,返回 Optional<T>
收集
- collect(Collector c) 將流轉(zhuǎn)換為其他形式病蛉,接收一個 Collector接口的實現(xiàn)
用于給Stream中元素做匯總的方法
toList
List<T>
把流中元素收集到List
List<Employee> emps = list.stream().collect(Collectors.toList());
Set<T>
把流中元素收集到Set
Set<Employee> emps = list.stream().collect(Collectors.toSet());
toCollection
Collection<T>
把流中元素收集到創(chuàng)建的集合
Collection<Employee>emps =list.stream().collect(Collectors.toCollection(ArrayList::new));
counting
Long
計算流中元素的個數(shù)
long count = list.stream().collect(Collectors.counting());
summingInt
Integer
對流中元素的整數(shù)屬性求和
int total = list.stream().collect(Collectors.summingInt(Employee::getSalary));
averagingInt
Double
計算流中元素Integer屬性的平均 值
double avg = list.stream().collect(Collectors.averagingInt(Employee::getSalary));
summarizingInt
IntSummaryStatistics
收集流中Integer屬性的統(tǒng)計值。 如:平均值
IntSummaryStatistics iss = list.stream().collect(Collectors.summarizingInt(Employee::getSalary));
joining
String
連接流中每個字符串
String str = list.stream().map(Employee::getName).collect(Collectors.joining());
maxBy
Optional<T>
根據(jù)比較器選擇最大值
Optional<Emp>max = list.stream().collect(Collectors.maxBy(comparingInt(Employee::getSalary)));
minBy
Optional<T>
根據(jù)比較器選擇最小值
Optional<Emp> min = list.stream().collect(Collectors.minBy(comparingInt(Employee::getSalary)));
reducing
歸約產(chǎn)生的類型
從一個作為累加器的初始值開始,利用BinaryOperator與 流中元素逐個結(jié)合铺然,從而歸約成單個值
int total = list.stream().collect(Collectors.reducing(0, Employee::getSalar, Integer::sum));
collectingAndThen
轉(zhuǎn)換函數(shù)返回的類型
包裹另一個收集器俗孝,對其結(jié) 果轉(zhuǎn)換函數(shù)
int how = list.stream().collect(Collectors.collectingAndThen(Collectors.toList(), List::size));
groupingBy
Map<K, List<T>>
根據(jù)某屬性值對流分組,屬 性為K魄健,結(jié)果為V
Map<Emp.Status, List<Emp>> map= list.stream() .collect(Collectors.groupingBy(Employee::getStatus));
partitioningBy
Map<Boolean, List<T>>
根據(jù)true或false進行分區(qū)
Map<Boolean,List<Emp>> vd = list.stream().collect(Collectors.partitioningBy(Employee::getManage));
5.并行流與串行流
并行流就是把一個內(nèi)容分成多個數(shù)據(jù)塊赋铝,并用不同的線程分別處理每個數(shù)據(jù)塊的流
可以使用parallel() 與 sequential() 在并行流與串行流之間進行切換
Fork/Join框架: 就是在必要的情況下,將一個大任務(wù)沽瘦,進行拆分(fork)成若干個小任務(wù)(拆到不可再拆時)革骨,再將一個個的小任務(wù)運算的結(jié)果進行join匯總.
采用 “工作竊取”模式(work-stealing): 當執(zhí)行新的任務(wù)時它可以將其拆分成更小的任務(wù)執(zhí)行,并將小任務(wù)加到線程隊列中析恋,然后再從一個隨機線程的隊列中偷一個并把它放在自己的隊列中
6.新時間日期 API
- LocalDate
- LocalTime
- LocalDateTime
now() 靜態(tài)方法良哲,根據(jù)當前時間創(chuàng)建對象
LocalDate localDate = LocalDate.now();
LocalTime localTime = LocalTime.now(); LocalDateTime localDateTime = LocalDateTime.now();
of() 靜態(tài)方法,根據(jù)指定日期/時間創(chuàng)建 對象
LocalDate localDate = LocalDate.of(2016, 10, 26);
LocalTime localTime = LocalTime.of(02, 22, 56);
LocalDateTime localDateTime = LocalDateTime.of(2016, 10, 26, 12, 10, 55);
plusDays, plusWeeks, plusMonths, plusYears 向當前 LocalDate 對象添加幾天助隧、 幾周筑凫、幾個月、幾年
minusDays, minusWeeks, minusMonths, minusYears 從當前 LocalDate 對象減去幾天喇颁、 幾周漏健、幾個月、幾年
plus, minus 添加或減少一個 Duration 或 Period
withDayOfMonth, withDayOfYear, withMonth, withYear 將月份天數(shù)橘霎、年份天數(shù)蔫浆、月份、年 份修改為指定的值并返回新的 LocalDate 對象
getDayOfMonth 獲得月份天數(shù)(1-31)
getDayOfYear 獲得年份天數(shù)(1-366)
getDayOfWeek 獲得星期幾(返回一個 DayOfWeek 枚舉值)
getMonth 獲得月份, 返回一個 Month 枚舉值
getMonthValue 獲得月份(1-12)
getYear 獲得年份
until 獲得兩個日期之間的 Period 對象姐叁, 或者指定 ChronoUnits 的數(shù)字
isBefore, isAfter 比較兩個 LocalDate
isLeapYear 判斷是否是閏年
- Instant 時間戳
Duration:用于計算兩個時間間隔
Period:用于計算兩個日期間隔
- TemporalAdjuster: 時間校正器
- 時間格式化
@Test
public void testDateFormat() {
LocalDateTime local = LocalDateTime.now();
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH:mm:ss");
System.out.println(formatter.format(local));
}
@Test
public void testDateFormat() {
LocalDateTime local = LocalDateTime.now();
String dateTime = local.format(DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH:mm:ss"));
System.out.println(dateTime);
}
@Test
public void testDateFormat() {
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH:mm:ss");
String strDate = "2018年05月12日 14:31:33";
LocalDateTime ldt = LocalDateTime.now();
LocalDateTime newDate = ldt.parse(strDate, dateTimeFormatter);
System.out.println(newDate);
}
7.接口中默認方法與靜態(tài)方法
接口默認方法的類優(yōu)先原則
若一個接口中定義了一個默認方法瓦盛,而另外一個父類或接口中又定義了一個同名的方法時選擇父類中的方法
如果一個父類提供了具體的實現(xiàn),那么接口中具有相同名稱和參數(shù)的默認方法會被忽略
接口沖突:
如果一個父接口提供一個默認方法外潜,而另一個接口也提供了一個具有相同名稱和參數(shù)列表的方法(不管方法是否是默認方法)原环,那么必須覆蓋該方法來解決沖突
8.Optional類
常用方法:
Optional.of(T t) : 創(chuàng)建一個 Optional 實例
Optional.empty() : 創(chuàng)建一個空的 Optional 實例
Optional.ofNullable(T t):若 t 不為 null,創(chuàng)建 Optional 實例,否則創(chuàng)建空實例
isPresent() : 判斷是否包含值
orElse(T t) : 如果調(diào)用對象包含值,返回該值处窥,否則返回t
orElseGet(Supplier s) :如果調(diào)用對象包含值嘱吗,返回該值,否則返回 s 獲取的值
map(Function f): 如果有值對其處理滔驾,并返回處理后的Optional谒麦,否則返回 Optional.empty()
flatMap(Function mapper):與 map 類似,要求返回值必須是Optional