Java8中l(wèi)ambda表達(dá)式的應(yīng)用及一些泛型相關(guān)知識(shí)
語法部分就不寫了,我們直接拋出一個(gè)實(shí)際問題,看看java8的這些新特性究竟能給我們帶來哪些便利
順帶用到一些泛型編程,一切都是為了簡(jiǎn)化代碼
場(chǎng)景:
一個(gè)數(shù)據(jù)類,用于記錄職工信息
public class Employee {
public String name;
public int age;
public char sex;
public String time;
public int salary;
}
我們有一列此類數(shù)據(jù)
List<Employee> data = Arrays.asList(e1,e2,e3......)
現(xiàn)在有需求:將員工Employee按照姓名的首字母(假設(shè)均為英文名)進(jìn)行分組:
那么我們要得到的結(jié)果應(yīng)該是一個(gè)Map:char -> List<Employee> 這樣的映射關(guān)系
public static Map<Character, List<Employee>> groupByFirstChar(
List<Employee> data){
Map<Character, List<Employee>> result = new HashMap<>();
for(Employee e : data){
Character c = e.name.charAt(0);
List<Employee> l = result.get(c);
if(l == null){
l = new ArrayList<>();
result.put(c, l);
}
l.add(e);
}
return result;
}
代碼并不復(fù)雜,很快就可以完成,老板看你效率這么高,于是說,再按照工資分個(gè)組吧,5000以下的,5000~10000的 ...等
也不會(huì)太難,將key換一下,稍作邏輯處理即可
public static Map<String, List<Employee>> groupBySalary(List<Employee> data) {
Map<String, List<Employee>> result = new HashMap<>();
for (Employee e : data) {
String key = separate(e.salary);
List<Employee> l = result.get(key);
if (l == null) {
l = new ArrayList<>();
result.put(key, l);
}
l.add(e);
}
return result;<br>}
private static String separate(int salary) {
if (salary <= 5000) {
return "5000以下";
}
if (salary <= 10000) {
return "5000~10000";
}
if (salary <= 20000) {
return "10000~20000";
}
return "20000以上"
}
然后老板又說了,按照員工的入職年份分下組吧。。。
這里就代碼就不寫了,稍作比較可以發(fā)現(xiàn),無論怎么分組,唯一的變化是key值的選取方式,
第一次將Employee的name的第一字母作為key:
Employee e -> e.name.charAt(0)
第二次將Employee的salary按照方法separat轉(zhuǎn)換為String作為key:
Employee e -> separate(e.salary):String
以此類推
Employee e -> getYear(e.time):String
事實(shí)上第一次也可以將獲取首字母單獨(dú)寫成一個(gè)方法
Employee e -> getFirstChar(e.name):Character
為了看起來更美觀,可以講三個(gè)方法的參數(shù)都設(shè)置成Employee 方法體就不寫了 這里只列出參數(shù)和返回值
Employee e -> getFirstChar(e) : Character Employee e -> separate(e) : String Employee e -> getYear(e) : String
->的左邊為參數(shù),:的右邊為返回值,->的右邊是方法的簽名
那么我們自然會(huì)想到將變化的部分抽取為參數(shù),其他不變的部分抽取為方法體,那么就可以省去那些重復(fù)的代碼,顯然變化的部分就是上面列出的,將Employee e轉(zhuǎn)化成key的方法,但是我們知道java是不能把方法作為參數(shù)進(jìn)行傳遞的。不過對(duì)于稍有經(jīng)驗(yàn)的程序猿來說這并不是問題,我們可以使用接口來實(shí)現(xiàn)我們的目的,同時(shí)又會(huì)遇到另一個(gè)問題,以上三個(gè)方法的返回值是不同的,因此我們要用到泛型:
public static <K> Map<K, List<Employee>> groupByKey(List<Employee> data, GetKey<K> getKey){
Map<K, List<Employee>> result = new HashMap<>();
for(Employee e : data) {
K key = getKey.getKey(e);
List<Employee> l = result.get(key);
if (l == null) {
l = new ArrayList<>();
result.put(key, l);
}
l.add(e);
}
return result;
}
interface GetKey<K>{
K getKey(Employee e);
}
那么上面的第一個(gè)需求就可以這樣實(shí)現(xiàn)
Map<Character, List<Employee>> result = groupByKey(data, new GetKey<Character>() {
@Override
public Character getKey(Employee e) {
e.name.charAt(0);
}
});
第二個(gè)需求
Map<String, List<Employee>> result = groupByKey(list, new GetKey<String>() {
@Override
public String getKey(Employee e) {
separate(e.salary);
}
});
可以發(fā)現(xiàn),我們只需要更改泛型參數(shù)和匿名內(nèi)部類的實(shí)現(xiàn)即可,唯一的問題恐怕是這么寫實(shí)在不太好看,而且很多例行公事的代碼,尤其體現(xiàn)在匿名內(nèi)部類上。
事實(shí)上我們只關(guān)心這個(gè)匿名內(nèi)部類的參數(shù)和返回值,其他部分僅僅是語法要求。
java8恰好為我們提供了很好的方式來避免復(fù)雜的例行公事的方式:lambda表達(dá)式,以上實(shí)現(xiàn)就可以寫成
Map<Character, List<Employee>> resultByFirstChar = groupByKey(list, e -> e.name.charAt(0)); Map<String, List<Employee>> resultBySalary = groupByKey(list, e -> separate(e.salary));
lambda表達(dá)式恰恰只表現(xiàn)出我們所關(guān)心的,參數(shù)和返回值,同時(shí)由于類型推斷,可以省去參數(shù)類型,具體語法這里就不介紹了,網(wǎng)上可以查到很多資料
extra:
如果你對(duì)泛型有不錯(cuò)的了解的話,方法groupByKey還可以進(jìn)一步抽象:
public static <K, E> Map<K, List<E>> groupBy(List<? extends E> data, Function<? super E, ? extends K> fun) {
Map<K, List<E>> result = new HashMap<>();
for(E e : data) {
K k = fun.apply(e);<br> List<E> l = result.get(k);
if(l == null) {
l = new ArrayList<>();
result.put(k, l);
}
l.add(e);
}
return result;<br>
}
我們將Employee這個(gè)類也抽取了,好處顯而易見
Function接口是java8新加入的接口:
@FunctionalInterface
public interface Function<T, R> {
R apply(T t);
}
輸入一個(gè)T類型 返回R類型。泛型和函數(shù)式編程結(jié)合的很不錯(cuò),雖然java8的新特性被各種吐槽,但是能帶來好處總是好的,這給了我們更多的選擇。
有時(shí)間的話會(huì)介紹stream,java8的另一大利器
以上所述是小編給大家介紹的Java8中l(wèi)ambda表達(dá)式的應(yīng)用及一些泛型相關(guān)知識(shí),希望對(duì)大家有所幫助,如果大家有任何疑問請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)腳本之家網(wǎng)站的支持!
相關(guān)文章
詳解spring security 配置多個(gè)AuthenticationProvider
這篇文章主要介紹了詳解spring security 配置多個(gè)AuthenticationProvider ,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-05-05
Spring中的事務(wù)管理及實(shí)現(xiàn)方式解析
這篇文章主要介紹了Spring中的事務(wù)管理及實(shí)現(xiàn)方式解析,Spring事務(wù)管理基于底層數(shù)據(jù)庫本身的事務(wù)處理機(jī)制,數(shù)據(jù)庫事務(wù)的基礎(chǔ),是掌握Spring事務(wù)管理的基礎(chǔ),這篇總結(jié)下Spring事務(wù),需要的朋友可以參考下2024-01-01
淺析Java中String與StringBuffer拼接的區(qū)別
String拼接會(huì)創(chuàng)建一個(gè)新的String對(duì)象,存儲(chǔ)拼接后的字符串,StringBuffer拼接是直接在本身拼接,會(huì)即時(shí)刷新。下面通過本文給大家介紹Java中String與StringBuffer拼接的區(qū)別,感興趣的朋友一起看看吧2017-06-06
Java實(shí)現(xiàn)一鍵生成表controller,service,mapper文件
這篇文章主要為大家詳細(xì)介紹了如何利用Java語言實(shí)現(xiàn)一鍵生成表controller,service,mapper文件,文中的示例代碼講解詳細(xì),需要的可以收藏一下2023-05-05
IDEA插件(BindED)之查看class文件的十六進(jìn)制
這篇文章主要介紹了IDEA插件(BindED)之查看class文件的十六進(jìn)制,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-12-12
IDEA新建springboot項(xiàng)目時(shí)未生成pom.xml文件的解決操作
這篇文章主要給大家介紹了關(guān)于IDEA新建springboot項(xiàng)目時(shí)未生成pom.xml文件的解決操作方法,文中通過實(shí)例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2023-02-02

