1 概述
最近在使用java做一些資料處理,發現使用java8新特性很好用,看着也很高大上,下面進行學習下.
2 初體驗
需求:按照字元長長度進行排序
- 原來的方式:Comparator() --> 匿名内部類
@Test
public void compareLength1(){
Comparator<String> comparator = new Comparator<String>() {
public int compare(String o1, String o2) {
return Integer.compare(o1.length(),o2.length());
}
};
TreeSet<String> set = new TreeSet<>(comparator);
set.add("a");
set.add("bb");
set.add("ccc");
for (String s : set) {
System.out.println(s);
}
}
- lambda表達式
@Test
public void compareLength2(){
Comparator<String> comparator = (x,y)-> Integer.compare(x.length(),y.length());
TreeSet<String> set = new TreeSet<>(comparator);
set.add("a");
set.add("bb");
set.add("ccc");
for (String s : set) {
System.out.println(s);
}
}
相信大家可以有一個簡單的認識了,直覺上來看寫法上更加簡潔了,看着更高大上了。肯定不止這些哈,用起來肯定更加友善,加快開發效率。下面我們繼續通過例子進行學習。
3 進一步認識lambda表達式
大家應該知道,使用sql語句可以很友善的進行各種條件過濾,選取TopN等需求,也是我們經常用到的,而在java中實作這些共能,在java8之前是沒有那麼多算子,寫法上也是相對複雜的。下面我們繼續lambda表達式的學習,後面也會學習一些其他的特性,Stream Api等。
3.1 需求:按指定條件過濾
- 實體類User
public class User {
private int id;
private String name;
private int age;
private Double salary;
public User(int id, String name, int age, Double salary) {
this.id = id;
this.name = name;
this.age = age;
this.salary = salary;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Double getSalary() {
return salary;
}
public void setSalary(Double salary) {
this.salary = salary;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", name='" + name + '\'' +
", age=" + age +
", salary=" + salary +
'}';
}
}
- 擷取年齡小于 35 的人員資訊
import org.junit.Test;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* 按條件過濾
*/
public class LambdaTrain2 {
List<User> emps = Arrays.asList(
new User(1, "張三", 18, 9999.9),
new User(2, "李四", 59, 7777.7),
new User(3, "王五", 28, 3333.33),
new User(4, "趙六", 8, 8888.88),
new User(5, "田七", 38, 5555.55)
);
//擷取年齡小于 35 的人員資訊
@Test
public void filterUser(){
List<User> list1 =new ArrayList<>();
for (User user : emps) {
if (user.getAge()<35) {
list1.add(user);
}
}
for (User user : list1) {
System.out.println(user);
}
}
- 現在需求變化,要求擷取薪水大于5000的人員資訊
//擷取薪水大于5000的人員資訊
@Test
public void filterUser1(){
List<User> list1 =new ArrayList<>();
for (User user : emps) {
if (user.getSalary()>5000.0) {
list1.add(user);
}
}
for (User user : list1) {
System.out.println(user);
}
}
小結: 目前功能是實作了但是大家有沒發現,這兩個方法其中 最主要的差別就是
if()
語句中的判斷條件,其他的都是一樣的,是以說這樣子寫并不是最好的。備援性太高。
3.2 優化:
- 政策設計模式
- 實作自定義過濾接口
public interface MyFilter<T> {
public boolean filter(T t);
}
- 設計根據年齡進行過濾FilterWithAge
public class FilterWithAge implements MyFilter<User> {
@Override
public boolean filter(User user) {
return user.getAge()<35;
}
}
- 設計根據薪水進行過濾FilterWithSalary
public class FilterWithAge implements MyFilter<User> {
@Override
public boolean filter(User user) {
return user.getSalary()>5000.0;
}
}
- 功能實作
//emps就是上面的list
//優化方式一:政策設計模式
public List<User> filterUser2(List<User> userList, MyFilter<User> myFilter){
List<User> list =new ArrayList<>();
for (User u: userList){
if (myFilter.filter(u)){
list.add(u);
}
}
return list;
}
@Test
public void test(){
//按照年齡小于35過濾
List<User> users = filterUser2(emps, new FilterWithAge());
for (User user:users){
System.out.println(user);
}
System.out.println("-------------------------------------");
//按照薪水大于
List<User> users1 = filterUser2(emps,new FilterWithSalary());
for (User user:users1){
System.out.println(user);
}
}
小結: 個人了解哈上面展現了一種面向接口程式設計,是一種優化方式,減少了備援代碼,但是個人感覺也挺繁瑣的又要寫接口,又要為每種過濾條件建立一個類…還是挺複雜的。下面我們繼續優化。
- 匿名内部類
//優化方式二:匿名内部類
@Test
public void test2(){
List<User> users = filterUser2(emps, new MyFilter<User>() {
@Override
public boolean filter(User user) {
return user.getId()>2;
}
});
for (User user:users){
System.out.println(user);
}
}
小結: 到這來感覺應該是很簡潔了,代碼看着也很高大上,哈哈哈。但是匿名内部類讓人看着就不是很好了解,
java8之後我們提供了更加簡潔的方式,下面進行我們的主題, java8新特性的使用。
- Lambda 表達式
//優化方式三:Lambda 表達式
@Test
public void test3(){
//調用上面寫的方法filterUser2()
List<User> users = filterUser2(emps, x -> x.getAge() < 35);
//調用提供的forEach方法
users.forEach(System.out::println);
}
小結: 上面就使用到了我們的Lambda表達式,是不是看着更簡潔,不用寫匿名内部類了哈,後面我們會講解為什麼可以這樣寫,其實就是函數式程式設計,實作内部已經實作的接口,就是一種文法糖.最後我們看看更簡潔的寫法。
也是我們後續所學的Stream API。
4. Stream API
//優化方式四:Stream API
//前面我們都是在調已經寫好的filterUser2方法,下面我們不使用試試看哈
@Test
public void test4(){
//按年齡賽選
emps.stream()
.filter(x-> x.getAge() < 35)
.forEach(System.out::println);
System.out.println("--------------------");
//按id篩選,排序,選top3
emps.stream()
.filter(x-> x.getId()>2)
.sorted((a,b)->b.getId()-a.getId()) //預設是升序
.limit(3)
.forEach(System.out::println);
}
總結: 你還不想學嗎?寫法夠裝逼嗎?學過scala的同學應該很熟悉,這種寫法跟scala好像啊。看到這裡我個人的想法的,牛批,反正我是想學!