激情久久久_欧美视频区_成人av免费_不卡视频一二三区_欧美精品在欧美一区二区少妇_欧美一区二区三区的

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|JAVA教程|ASP教程|

香港云服务器
服務器之家 - 編程語言 - JAVA教程 - Java Lambda表達式詳解和實例

Java Lambda表達式詳解和實例

2019-11-23 16:58Java教程網 JAVA教程

這篇文章主要介紹了Java Lambda表達式詳細介紹,從簡單的到復雜的實例講解,需要的朋友可以參考下

簡介

Lambda表達式Java SE 8中一個重要的新特性。lambda表達式允許你通過表達式來代替功能接口。 lambda表達式就和方法一樣,它提供了一個正常的參數(shù)列表和一個使用這些參數(shù)的主體(body,可以是一個表達式或一個代碼塊)。

Lambda表達式還增強了集合庫。 Java SE 8添加了2個對集合數(shù)據(jù)進行批量操作的包: java.util.function 包以及 java.util.stream 包。 流(stream)就如同迭代器(iterator),但附加了許多額外的功能。 總的來說,lambda表達式和 stream 是自Java語言添加泛型(Generics)和注解(annotation)以來最大的變化。 在本文中,我們將從簡單到復雜的示例中見認識lambda表達式和stream的強悍。

環(huán)境準備

如果還沒有安裝Java 8,那么你應該先安裝才能使用lambda和stream(譯者建議在虛擬機中安裝,測試使用)。 像NetBeans 和IntelliJ IDEA 一類的工具和IDE就支持Java 8特性,包括lambda表達式,可重復的注解,緊湊的概要文件和其他特性。

Lambda表達式的語法

基本語法:
(parameters) -> expression

(parameters) ->{ statements; }

下面是Java lambda表達式的簡單例子:

 

復制代碼代碼如下:


// 1. 不需要參數(shù),返回值為 5
() -> 5

 

// 2. 接收一個參數(shù)(數(shù)字類型),返回其2倍的值
x -> 2 * x

// 3. 接受2個參數(shù)(數(shù)字),并返回他們的差值
(x, y) -> x – y

// 4. 接收2個int型整數(shù),返回他們的和
(int x, int y) -> x + y

// 5. 接受一個 string 對象,并在控制臺打印,不返回任何值(看起來像是返回void)
(String s) -> System.out.print(s)

 

基本的Lambda例子

現(xiàn)在,我們已經知道什么是lambda表達式,讓我們先從一些基本的例子開始。 在本節(jié)中,我們將看到lambda表達式如何影響我們編碼的方式。 假設有一個玩家List ,程序員可以使用 for 語句 ("for 循環(huán)")來遍歷,在Java SE 8中可以轉換為另一種形式:

 

復制代碼代碼如下:


String[] atp = {"Rafael Nadal", "Novak Djokovic",
       "Stanislas Wawrinka",
       "David Ferrer","Roger Federer",
       "Andy Murray","Tomas Berdych",
       "Juan Martin Del Potro"};
List<String> players =  Arrays.asList(atp);

 

// 以前的循環(huán)方式
for (String player : players) {
     System.out.print(player + "; ");
}

// 使用 lambda 表達式以及函數(shù)操作(functional operation)
players.forEach((player) -> System.out.print(player + "; "));

// 在 Java 8 中使用雙冒號操作符(double colon operator)
players.forEach(System.out::println);

 

正如您看到的,lambda表達式可以將我們的代碼縮減到一行。 另一個例子是在圖形用戶界面程序中,匿名類可以使用lambda表達式來代替。 同樣,在實現(xiàn)Runnable接口時也可以這樣使用:

 

復制代碼代碼如下:


// 使用匿名內部類
btn.setOnAction(new EventHandler<ActionEvent>() {
          @Override
          public void handle(ActionEvent event) {
              System.out.println("Hello World!"); 
          }
    });

// 或者使用 lambda expression
btn.setOnAction(event -> System.out.println("Hello World!"));

 

 

 

下面是使用lambdas 來實現(xiàn) Runnable接口 的示例:

 

復制代碼代碼如下:


// 1.1使用匿名內部類
new Thread(new Runnable() {
    @Override
    public void run() {
        System.out.println("Hello world !");
    }
}).start();

 

// 1.2使用 lambda expression
new Thread(() -> System.out.println("Hello world !")).start();

// 2.1使用匿名內部類
Runnable race1 = new Runnable() {
    @Override
    public void run() {
        System.out.println("Hello world !");
    }
};

// 2.2使用 lambda expression
Runnable race2 = () -> System.out.println("Hello world !");

// 直接調用 run 方法(沒開新線程哦!)
race1.run();
race2.run();

 


Runnable 的 lambda表達式,使用塊格式,將五行代碼轉換成單行語句。 接下來,在下一節(jié)中我們將使用lambdas對集合進行排序。

使用Lambdas排序集合

在Java中,Comparator 類被用來排序集合。 在下面的例子中,我們將根據(jù)球員的 name, surname, name 長度 以及最后一個字母。 和前面的示例一樣,先使用匿名內部類來排序,然后再使用lambda表達式精簡我們的代碼。
在第一個例子中,我們將根據(jù)name來排序list。 使用舊的方式,代碼如下所示:

 

復制代碼代碼如下:

String[] players = {"Rafael Nadal", "Novak Djokovic", 
    "Stanislas Wawrinka", "David Ferrer",
    "Roger Federer", "Andy Murray",
    "Tomas Berdych", "Juan Martin Del Potro",
    "Richard Gasquet", "John Isner"};

// 1.1 使用匿名內部類根據(jù) name 排序 players
Arrays.sort(players, new Comparator<String>() {
    @Override
    public int compare(String s1, String s2) {
        return (s1.compareTo(s2));
    }
});

 

使用lambdas,可以通過下面的代碼實現(xiàn)同樣的功能:

 

復制代碼代碼如下:


// 1.2 使用 lambda expression 排序 players
Comparator<String> sortByName = (String s1, String s2) -> (s1.compareTo(s2));
Arrays.sort(players, sortByName);

 

// 1.3 也可以采用如下形式:
Arrays.sort(players, (String s1, String s2) -> (s1.compareTo(s2)));

 

其他的排序如下所示。 和上面的示例一樣,代碼分別通過匿名內部類和一些lambda表達式來實現(xiàn)Comparator :

 

復制代碼代碼如下:


// 1.1 使用匿名內部類根據(jù) surname 排序 players
Arrays.sort(players, new Comparator<String>() {
    @Override
    public int compare(String s1, String s2) {
        return (s1.substring(s1.indexOf(" ")).compareTo(s2.substring(s2.indexOf(" "))));
    }
});

 

// 1.2 使用 lambda expression 排序,根據(jù) surname
Comparator<String> sortBySurname = (String s1, String s2) -> 
    ( s1.substring(s1.indexOf(" ")).compareTo( s2.substring(s2.indexOf(" ")) ) );
Arrays.sort(players, sortBySurname);

// 1.3 或者這樣,懷疑原作者是不是想錯了,括號好多...
Arrays.sort(players, (String s1, String s2) -> 
      ( s1.substring(s1.indexOf(" ")).compareTo( s2.substring(s2.indexOf(" ")) ) ) 
    );

// 2.1 使用匿名內部類根據(jù) name lenght 排序 players
Arrays.sort(players, new Comparator<String>() {
    @Override
    public int compare(String s1, String s2) {
        return (s1.length() - s2.length());
    }
});

// 2.2 使用 lambda expression 排序,根據(jù) name lenght
Comparator<String> sortByNameLenght = (String s1, String s2) -> (s1.length() - s2.length());
Arrays.sort(players, sortByNameLenght);

// 2.3 or this
Arrays.sort(players, (String s1, String s2) -> (s1.length() - s2.length()));

// 3.1 使用匿名內部類排序 players, 根據(jù)最后一個字母
Arrays.sort(players, new Comparator<String>() {
    @Override
    public int compare(String s1, String s2) {
        return (s1.charAt(s1.length() - 1) - s2.charAt(s2.length() - 1));
    }
});

// 3.2 使用 lambda expression 排序,根據(jù)最后一個字母
Comparator<String> sortByLastLetter = 
    (String s1, String s2) -> 
        (s1.charAt(s1.length() - 1) - s2.charAt(s2.length() - 1));
Arrays.sort(players, sortByLastLetter);

// 3.3 or this
Arrays.sort(players, (String s1, String s2) -> (s1.charAt(s1.length() - 1) - s2.charAt(s2.length() - 1)));

 

 

就是這樣,簡潔又直觀。 在下一節(jié)中我們將探索更多l(xiāng)ambdas的能力,并將其與 stream 結合起來使用。

使用Lambdas和Streams

Stream是對集合的包裝,通常和lambda一起使用。 使用lambdas可以支持許多操作,如 map, filter, limit, sorted, count, min, max, sum, collect 等等。 同樣,Stream使用懶運算,他們并不會真正地讀取所有數(shù)據(jù),遇到像getFirst() 這樣的方法就會結束鏈式語法。 在接下來的例子中,我們將探索lambdas和streams 能做什么。 我們創(chuàng)建了一個Person類并使用這個類來添加一些數(shù)據(jù)到list中,將用于進一步流操作。 Person 只是一個簡單的POJO類:

 

復制代碼代碼如下:


public class Person {

 

private String firstName, lastName, job, gender;
private int salary, age;

public Person(String firstName, String lastName, String job,
                String gender, int age, int salary)       {
          this.firstName = firstName;
          this.lastName = lastName;
          this.gender = gender;
          this.age = age;
          this.job = job;
          this.salary = salary;
}
// Getter and Setter 
// . . . . .
}

 

接下來,我們將創(chuàng)建兩個list,都用來存放Person對象:

 

復制代碼代碼如下:


List<Person> javaProgrammers = new ArrayList<Person>() {
  {
    add(new Person("Elsdon", "Jaycob", "Java programmer", "male", 43, 2000));
    add(new Person("Tamsen", "Brittany", "Java programmer", "female", 23, 1500));
    add(new Person("Floyd", "Donny", "Java programmer", "male", 33, 1800));
    add(new Person("Sindy", "Jonie", "Java programmer", "female", 32, 1600));
    add(new Person("Vere", "Hervey", "Java programmer", "male", 22, 1200));
    add(new Person("Maude", "Jaimie", "Java programmer", "female", 27, 1900));
    add(new Person("Shawn", "Randall", "Java programmer", "male", 30, 2300));
    add(new Person("Jayden", "Corrina", "Java programmer", "female", 35, 1700));
    add(new Person("Palmer", "Dene", "Java programmer", "male", 33, 2000));
    add(new Person("Addison", "Pam", "Java programmer", "female", 34, 1300));
  }
};

 

List<Person> phpProgrammers = new ArrayList<Person>() {
  {
    add(new Person("Jarrod", "Pace", "PHP programmer", "male", 34, 1550));
    add(new Person("Clarette", "Cicely", "PHP programmer", "female", 23, 1200));
    add(new Person("Victor", "Channing", "PHP programmer", "male", 32, 1600));
    add(new Person("Tori", "Sheryl", "PHP programmer", "female", 21, 1000));
    add(new Person("Osborne", "Shad", "PHP programmer", "male", 32, 1100));
    add(new Person("Rosalind", "Layla", "PHP programmer", "female", 25, 1300));
    add(new Person("Fraser", "Hewie", "PHP programmer", "male", 36, 1100));
    add(new Person("Quinn", "Tamara", "PHP programmer", "female", 21, 1000));
    add(new Person("Alvin", "Lance", "PHP programmer", "male", 38, 1600));
    add(new Person("Evonne", "Shari", "PHP programmer", "female", 40, 1800));
  }
};

 

現(xiàn)在我們使用forEach方法來迭代輸出上述列表:

 

復制代碼代碼如下:

System.out.println("所有程序員的姓名:");
javaProgrammers.forEach((p) -> System.out.printf("%s %s; ", p.getFirstName(), p.getLastName()));
phpProgrammers.forEach((p) -> System.out.printf("%s %s; ", p.getFirstName(), p.getLastName()));

 

我們同樣使用forEach方法,增加程序員的工資5%:

 

復制代碼代碼如下:


System.out.println("給程序員加薪 5% :");
Consumer<Person> giveRaise = e -> e.setSalary(e.getSalary() / 100 * 5 + e.getSalary());

 

javaProgrammers.forEach(giveRaise);
phpProgrammers.forEach(giveRaise);

 

另一個有用的方法是過濾器filter() ,讓我們顯示月薪超過1400美元的PHP程序員:

 

復制代碼代碼如下:

System.out.println("下面是月薪超過 $1,400 的PHP程序員:")
phpProgrammers.stream()
          .filter((p) -> (p.getSalary() > 1400))
          .forEach((p) -> System.out.printf("%s %s; ", p.getFirstName(), p.getLastName()));

 

我們也可以定義過濾器,然后重用它們來執(zhí)行其他操作:

復制代碼代碼如下:


// 定義 filters
Predicate<Person> ageFilter = (p) -> (p.getAge() > 25);
Predicate<Person> salaryFilter = (p) -> (p.getSalary() > 1400);
Predicate<Person> genderFilter = (p) -> ("female".equals(p.getGender()));

 

System.out.println("下面是年齡大于 24歲且月薪在$1,400以上的女PHP程序員:");
phpProgrammers.stream()
          .filter(ageFilter)
          .filter(salaryFilter)
          .filter(genderFilter)
          .forEach((p) -> System.out.printf("%s %s; ", p.getFirstName(), p.getLastName()));

// 重用filters
System.out.println("年齡大于 24歲的女性 Java programmers:");
javaProgrammers.stream()
          .filter(ageFilter)
          .filter(genderFilter)
          .forEach((p) -> System.out.printf("%s %s; ", p.getFirstName(), p.getLastName()));

 

 

使用limit方法,可以限制結果集的個數(shù):

 

復制代碼代碼如下:


System.out.println("最前面的3個 Java programmers:");
javaProgrammers.stream()
          .limit(3)
          .forEach((p) -> System.out.printf("%s %s; ", p.getFirstName(), p.getLastName()));

 


System.out.println("最前面的3個女性 Java programmers:");
javaProgrammers.stream()
          .filter(genderFilter)
          .limit(3)
          .forEach((p) -> System.out.printf("%s %s; ", p.getFirstName(), p.getLastName()));

 

排序呢? 我們在stream中能處理嗎? 答案是肯定的。 在下面的例子中,我們將根據(jù)名字和薪水排序Java程序員,放到一個list中,然后顯示列表:

 

復制代碼代碼如下:


System.out.println("根據(jù) name 排序,并顯示前5個 Java programmers:");
List<Person> sortedJavaProgrammers = javaProgrammers
          .stream()
          .sorted((p, p2) -> (p.getFirstName().compareTo(p2.getFirstName())))
          .limit(5)
          .collect(toList());

 

sortedJavaProgrammers.forEach((p) -> System.out.printf("%s %s; %n", p.getFirstName(), p.getLastName()));

System.out.println("根據(jù) salary 排序 Java programmers:");
sortedJavaProgrammers = javaProgrammers
          .stream()
          .sorted( (p, p2) -> (p.getSalary() - p2.getSalary()) )
          .collect( toList() );

sortedJavaProgrammers.forEach((p) -> System.out.printf("%s %s; %n", p.getFirstName(), p.getLastName()));

 

如果我們只對最低和最高的薪水感興趣,比排序后選擇第一個/最后一個 更快的是min和max方法:

 

復制代碼代碼如下:


System.out.println("工資最低的 Java programmer:");
Person pers = javaProgrammers
          .stream()
          .min((p1, p2) -> (p1.getSalary() - p2.getSalary()))
          .get()

 

System.out.printf("Name: %s %s; Salary: $%,d.", pers.getFirstName(), pers.getLastName(), pers.getSalary())

System.out.println("工資最高的 Java programmer:");
Person person = javaProgrammers
          .stream()
          .max((p, p2) -> (p.getSalary() - p2.getSalary()))
          .get()

System.out.printf("Name: %s %s; Salary: $%,d.", person.getFirstName(), person.getLastName(), person.getSalary())

 

上面的例子中我們已經看到 collect 方法是如何工作的。 結合 map 方法,我們可以使用 collect 方法來將我們的結果集放到一個字符串,一個 Set 或一個TreeSet中:

 

復制代碼代碼如下:


System.out.println("將 PHP programmers 的 first name 拼接成字符串:");
String phpDevelopers = phpProgrammers
          .stream()
          .map(Person::getFirstName)
          .collect(joining(" ; ")); // 在進一步的操作中可以作為標記(token)  

 

System.out.println("將 Java programmers 的 first name 存放到 Set:");
Set<String> javaDevFirstName = javaProgrammers
          .stream()
          .map(Person::getFirstName)
          .collect(toSet());

System.out.println("將 Java programmers 的 first name 存放到 TreeSet:");
TreeSet<String> javaDevLastName = javaProgrammers
          .stream()
          .map(Person::getLastName)
          .collect(toCollection(TreeSet::new));

 

 

Streams 還可以是并行的(parallel)。 示例如下:

 

復制代碼代碼如下:

System.out.println("計算付給 Java programmers 的所有money:");
int totalSalary = javaProgrammers
          .parallelStream()
          .mapToInt(p -> p.getSalary())
          .sum();

 

我們可以使用summaryStatistics方法獲得stream 中元素的各種匯總數(shù)據(jù)。 接下來,我們可以訪問這些方法,比如getMax, getMin, getSum或getAverage:

 

復制代碼代碼如下:


//計算 count, min, max, sum, and average for numbers
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
IntSummaryStatistics stats = numbers
          .stream()
          .mapToInt((x) -> x)
          .summaryStatistics();

 

System.out.println("List中最大的數(shù)字 : " + stats.getMax());
System.out.println("List中最小的數(shù)字 : " + stats.getMin());
System.out.println("所有數(shù)字的總和   : " + stats.getSum());
System.out.println("所有數(shù)字的平均值 : " + stats.getAverage()); 

 

OK,就這樣,希望你喜歡它!

總結

在本文中,我們學會了使用lambda表達式的不同方式,從基本的示例,到使用lambdas和streams的復雜示例。 此外,我們還學習了如何使用lambda表達式與Comparator 類來對Java集合進行排序。


譯者注:雖然看著很先進,其實Lambda表達式的本質只是一個"語法糖",由編譯器推斷并幫你轉換包裝為常規(guī)的代碼,因此你可以使用更少的代碼來實現(xiàn)同樣的功能。本人建議不要亂用,因為這就和某些很高級的黑客寫的代碼一樣,簡潔,難懂,難以調試,維護人員想罵娘.

延伸 · 閱讀

精彩推薦
542
Weibo Article 1 Weibo Article 2 Weibo Article 3 Weibo Article 4 Weibo Article 5 Weibo Article 6 Weibo Article 7 Weibo Article 8 Weibo Article 9 Weibo Article 10 Weibo Article 11 Weibo Article 12 Weibo Article 13 Weibo Article 14 Weibo Article 15 Weibo Article 16 Weibo Article 17 Weibo Article 18 Weibo Article 19 Weibo Article 20 Weibo Article 21 Weibo Article 22 Weibo Article 23 Weibo Article 24 Weibo Article 25
主站蜘蛛池模板: 成人午夜免费在线观看 | xxx日本视频 | 久久久久夜色精品国产老牛91 | 成人免费福利视频 | 欧美成人高清在线 | 久久综合九色综合久久久精品综合 | 91精品老司机 | 国产精选电影免费在线观看 | 午夜视频在线观 | 热99热 | 亚洲性生活视频 | 久久精品一区视频 | 天天透天天狠天天爱综合97 | 羞羞视频免费网站含羞草 | 天堂在线资源av | 91情侣在线偷精品国产 | 一区二区三区欧美在线观看 | 亚欧美一区二区 | 污版视频在线观看 | 毛片视频在线免费观看 | 欧美黄在线 | 一级毛片在线看 | 毛片视频免费播放 | www.国产一区.com | 成年免费大片黄在线观看岛国 | 国产88久久久国产精品免费二区 | 日日做夜夜操 | 欧美视频不卡 | 免费在线观看毛片视频 | 免费毛片随便看 | 超碰人人做人人爱 | 毛片久久 | xxx日本视频 | 欧美成人精品一区二区 | 性大片性大片免费 | av电影网站在线 | 91网页| 国产精品视频一区二区三区四区五区 | 一级一级一级毛片 | 毛片视频网站在线观看 | 国产黄色一区二区 |