day41
JDK1.8新特性
JDK1.8新特性簡介
- 速度更快 - 優(yōu)化底層源碼,比如HashMap、ConcurrentHashMap
- 代碼更少 - 添加新的語法Lambda表達(dá)式
- 強(qiáng)大的Stream API
- 便于并行
- 最大化減少空指針異常 - Optional
Lambda表達(dá)式
簡介
Lambda是一個匿名函數(shù)(方法), 允許把函數(shù)作為一個方法的參數(shù) 。利用Lambda表達(dá)式可以寫出更簡潔、更靈活的代碼。作為一種更緊湊的代碼風(fēng)格,使Java的語言表達(dá)能力得到了提升。
一般都是優(yōu)化匿名內(nèi)部類
基礎(chǔ)語法
無參數(shù)、無返回值的抽象方法
public class Test1 {
@Test
public void test01() {
// I1 i1 = new I1() {
// @Override
// public void method() {
// System.out.println("傳統(tǒng)使用匿名內(nèi)部類的方式");
// }
// };
// i1.method();
// I1 i1 = ()->{
// System.out.println("使用lambda表達(dá)式的方式");
// };
// i1.method();
//lambda表達(dá)式里面只有一個語句情況,大括號可以省略進(jìn)行簡化代碼
I1 i1 = ()-> System.out.println("采用Lambda表達(dá)式的方式");
i1.method();
}
}
interface I1{
public void method();//無參數(shù)、無返回值的抽象方法
}
一個參數(shù)、無返回值的抽象方法
外部new匿名內(nèi)部類調(diào)用方法時,參數(shù)看接口定義的規(guī)范里的參數(shù)類型
public class Test01 {
public static void main(String[] args) {
// I1 i1 = new I1() {
// @Override
// public void method(String str) {
// System.out.println("使用傳統(tǒng)匿名內(nèi)部類的方式:" + str);
// }
// };
// i1.method("過往云煙");
// I1 i1 = (String str)->{
// System.out.println("使用lambda表達(dá)式的方式:" + str);
// };
// i1.method("過往云煙");
// I1 i1 = (String str)->System.out.println("使用lambda表達(dá)式的方式:" + str);
// i1.method("過往云煙");
// I1 i1 = (str)->System.out.println("使用lambda表達(dá)式的方式:" + str);
// i1.method("過往云煙");
I1 i1 = str->System.out.println("使用lambda表達(dá)式的方式:" + str);
i1.method("過往云煙");
}
}
public interface I1 {
public void method(String str);//一個參數(shù)、無返回值的抽象方法
}
多個參數(shù)、無返回值的抽象方法
public class Test01 {
public static void main(String[] args) {
// I1 i1 = new I1() {
// @Override
// public void method(String str, int i) {
// System.out.println("使用傳統(tǒng)匿名內(nèi)部類的方式:" + str + " -- " + i);
// }
// };
// i1.method("過往云煙", 666);
// I1 i1 = (String str,int i)->{
// System.out.println("使用lambda表達(dá)式的方式:" + str + " -- " + i);
// };
// i1.method("過往云煙", 777);
// I1 i1 = (String str,int i)->System.out.println("使用lambda表達(dá)式的方式:" + str + " -- " + i);
// i1.method("過往云煙", 888);
I1 i1 = (str, i)->System.out.println("使用lambda表達(dá)式的方式:" + str + " -- " + i);
i1.method("過往云煙", 999);
}
}
public interface I1 {
//多個參數(shù)、無返回值的抽象方法
public void method(String str,int i);
}
多個參數(shù)、有返回值的抽象方法
public class Test01 {
public static void main(String[] args) {
// I1 i1 = new I1() {
// @Override
// public String method(int a, int b) {
// return "使用傳統(tǒng)匿名內(nèi)部類的方式:" + (a+b);
// }
// };
// String method = i1.method(10, 10);
// System.out.println(method);
// I1 i1 = (int a,int b)->{
// return "使用lambda表達(dá)式的方式:" + (a+b);
// };
// String method = i1.method(20, 20);
// System.out.println(method);
I1 i1 = (a, b)-> "使用lambda表達(dá)式的方式:" + (a+b);
String method = i1.method(30, 30);
System.out.println(method);
}
}
public interface I1 {
//多個參數(shù)、有返回值的抽象方法
public String method(int a,int b);
}
注意點
- 重寫方法的形參只有一個時,可以不加小括號
- Lambda表達(dá)式當(dāng)中不允許聲明一個與局部變量同名的參數(shù)或者局部變量
- Lambda表達(dá)式中訪問外層的局部變量,外層的局部變量自動變成隱式常量,默認(rèn)添加final
- 重寫方法的形參同時加類型或同時不加類型
public class Test1 {
@Test
public void test01() {
int x;
int num = 10;
I1 i1 = x -> System.out.println(x + (num++));
i1.method(1000);
I2 i2 = (int x,int y) -> {
int result = x+y;
return result;
};
int result = i2.method(10, 20);
System.out.println(result);
}
}
interface I1{
public void method(int num1);
}
interface I2{
public int method(int num1,int num2);
}
案例
案例1
1.調(diào)用Collections.sort()方法,通過定制排序比較兩個Student對象(先按年齡比較,年齡相同按照薪資比較),使用Lambda表達(dá)式作為參數(shù)傳遞
注意:比較時注意不能用減,因為doublue減后的小數(shù)會在轉(zhuǎn)int損失精度,ps:0.2變?yōu)?
public class Test01 {
public static void main(String[] args) {
List<Student> stuList = Arrays.asList(
new Student("張三", 28, 4800,Course.JAVA),
new Student("李四", 36, 7200,Course.JAVA),
new Student("王五", 19, 9600,Course.HTML),
new Student("趙六", 42, 6100,Course.HTML),
new Student("孫七", 23, 9600,Course.PYTHON),
new Student("吳八", 28, 3000,Course.PYTHON));
// Collections.sort(stuList, new Comparator<Student>() {
// @Override
// public int compare(Student o1, Student o2) {
// if(o1.equals(o2)){
// return 0;
// }
//
// int compare = Integer.compare(o1.getAge(), o2.getAge());
// if(compare != 0){
// return compare;
// }
//
// return Double.compare(o1.getSalary(), o2.getSalary());
// }
// });
Collections.sort(stuList, (o1,o2)->{
if(o1.equals(o2)){
return 0;
}
int compare = Integer.compare(o1.getAge(), o2.getAge());
if(compare != 0){
return compare;
}
return Double.compare(o1.getSalary(), o2.getSalary());
});
for (Student stu : stuList) {
System.out.println(stu);
}
}
}
public enum Course{//課程枚舉
JAVA,HTML,PYTHON;
}
public class Student{//學(xué)生類
private String name;
private int age;
private double salary;
private Course course;
//有參、無參、get、set方法【略】
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + age;
result = prime * result + ((course == null) ? 0 : course.hashCode());
result = prime * result + ((name == null) ? 0 : name.hashCode());
long temp;
temp = Double.doubleToLongBits(salary);
result = prime * result + (int) (temp ^ (temp >>> 32));
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Student other = (Student) obj;
if (age != other.age)
return false;
if (course != other.course)
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
if (Double.doubleToLongBits(salary) != Double.doubleToLongBits(other.salary))
return false;
return true;
}
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
builder.append("Student [name=");
builder.append(name);
builder.append(", age=");
builder.append(age);
builder.append(", salary=");
builder.append(salary);
builder.append(", course=");
builder.append(course);
builder.append("]");
return builder.toString();
}
}
案例2
2.創(chuàng)建I1接口,創(chuàng)建抽象方法:public String getValue(String str),在測試類中編寫方法使用接口作為參數(shù),將一個字符串轉(zhuǎn)為大寫,并作為方法的返回值
public class Test01 {
public static void main(String[] args) {
String str = method("abc", (x)-> {
return x.toUpperCase();
});
System.out.println(str);
}
public static String method(String str,I1 i1){
return i1.getValue(str);
}
}
interface I1{
public String getValue(String str);
}
案例3
3.創(chuàng)建I1<T,R>接口,泛型T為參數(shù),R為返回值,創(chuàng)建抽象方法:public R add(T t1,T t2),在測試類中編寫方法使用接口作為參數(shù),計算兩個long類型的和
public class Test01 {
public static void main(String[] args) {
long addLong = addLong(100,200,(a,b)->{
return a+b;
});
System.out.println(addLong);
}
public static long addLong(long l1,long l2,I1<Long,Long> i1){
return i1.add(l1, l2);
}
}
interface I1<T,R>{
public R add(T t1,T t2);
}
函數(shù)式接口
簡介
函數(shù)式接口是指僅僅只包含一個抽象方法的接口,jdk1.8提供了一個@FunctionalInterface注解來定義函數(shù)式接口,如果我們定義的接口不符合函數(shù)式的規(guī)范便會報錯。配合Lambda表達(dá)式一起使用
四大核心函數(shù)式接口
函數(shù)式接口 | 參數(shù)類型 | 返回類型 | 用途 |
---|---|---|---|
Consumer 消費型接口 | T | void | void accept(T t); |
Supplier 供給型接口 | void | T | T get(); |
Function<T, R> 函數(shù)型接口 | T | R | R apply(T t); |
Predicate 斷言型接口 | T | boolean | booelan test(T t); |
BiConsumer<T, U> | T,U | void | 對類型為T,U參數(shù)應(yīng)用操作。包含方法為void accept(T t,U u); |
BiFunction<T, U, R> | T,U | R | 對類型為T,U參數(shù)應(yīng)用操作,并返回R類型的結(jié)果。包含方法為R apply(T t,U u); |
UnaryOperator extends Function<T, T> | T | T | 對類型為T的對象進(jìn)行一元運算,并返回T類型的結(jié)果。包含方法為T apply(T t); |
BinaryOperator extends BiFunction<T,T,T> | T,T | T | 對類型為T的對象進(jìn)行二元運算,并返回T類型的結(jié)果。包含方法為T apply(T t1,T t2); |
ToIntFunction ToLongFunction ToDoubleFunction | T | int long double | 分別計算int、long、double值的函數(shù) |
IntFunction LongFunction DoubleFunction | int long double | R | 參數(shù)為int、long、double類型的函數(shù) |
應(yīng)用場景:當(dāng)項目中需要一個接口,并且該接口中只有一個抽象方法,就沒必要去創(chuàng)建新的接口,直接選擇Java提供的使用合適的函數(shù)式接口即可
案例替換
對Lambda表達(dá)式案例,使用合適的函數(shù)式接口去替換I1
創(chuàng)建I1接口,創(chuàng)建抽象方法:public String getValue(String str),
在測試類中編寫方法使用接口作為參數(shù),將一個字符串轉(zhuǎn)為大寫,并作為方法的返回值
注意:使用合適的函數(shù)式接口去替換I1
函數(shù)和方法:前端習(xí)慣稱函數(shù),后端習(xí)慣稱方法,簡單理解一個意思但非區(qū)別
函數(shù)式接口,一個抽象方法,超過就會報錯
函數(shù)式接口替換接口,就案例來看更改方法里的接口,用函數(shù)調(diào)用方法,少一層
public class Test01 {
public static void main(String[] args) {
String str = method("abc", (x)->{
return x.toUpperCase();
});
System.out.println(str);
}
public static String method(String str,Function<String, String> fun){
return fun.apply(str);
}
}
public class Test02 {
public static void main(String[] args) {
String str = method("abc", (x)->{
return x.toUpperCase();
});
System.out.println(str);
}
public static String method(String str,UnaryOperator<String> uo){
return uo.apply(str);
}
}
創(chuàng)建I1<T,R>接口,泛型T為參數(shù),R為返回值,創(chuàng)建抽象方法:public R add(T t1,T t2),
在測試類中編寫方法使用接口作為參數(shù),計算兩個long類型的和
public class Test01 {
public static void main(String[] args) {
long addLong = addLong(100,200,(a,b)->{
return a+b;
});
System.out.println(addLong);
}
public static long addLong(long l1,long l2,BiFunction<Long, Long, Long> bf){
return bf.apply(l1, l2);
}
}
public class Test02 {
public static void main(String[] args) {
long addLong = addLong(100,200,(a,b)->{
return a+b;
});
System.out.println(addLong);
}
public static long addLong(long l1,long l2,BinaryOperator<Long> bo){
return bo.apply(l1, l2);
}
}
總結(jié)
1.lambda表達(dá)式(其實就有優(yōu)化匿名內(nèi)部類的方案)
注意:使用lambda表達(dá)式必須有多態(tài)的思想2.函數(shù)式接口
該接口中只有一個抽象方法
@FunctionInterface這個注解表示該接口是函數(shù)式接口文章來源:http://www.zghlxwxcb.cn/news/detail-857579.html經(jīng)驗:
如果你想玩轉(zhuǎn)lambda表達(dá)式,必須先去學(xué)習(xí)匿名內(nèi)部類+多態(tài)
函數(shù)式接口應(yīng)用場景:需求要你寫個接口,這個接口只有一個抽象方法,就用函數(shù)式接口去代替文章來源地址http://www.zghlxwxcb.cn/news/detail-857579.html
到了這里,關(guān)于JDK1.8新特性(部分)【Lambda表達(dá)式、函數(shù)式接口】--學(xué)習(xí)JavaEE的day41的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!