1. 程式人生 > >JAVA基礎知識|lambda與stream

JAVA基礎知識|lambda與stream

view 兩個 方法 testcase alt except 上海 sort unit

lambda與stream是java8中比較重要兩個新特性,lambda表達式采用一種簡潔的語法定義代碼塊,允許我們將行為傳遞到函數中。之前我們想將行為傳遞到函數中,僅有的選擇是使用匿名內部類,現在我們可以使用lambda表達式替代匿名內部類。在學習lambda表達式之前,建議各位看官先去學習一下匿名內部類(JAVA基礎知識|內部類)。

stream提供了很多有用的api,方便了我們對集合的操作

一、lambda表達式

基本語法:
(parameters) -> expression

(parameters) ->{ statements; }

lambda表達式的重要特征:

  • 可選類型聲明:不需要聲明參數類型,編譯器可以統一識別參數值。
  • 可選的參數圓括號:一個參數無需定義圓括號,但多個參數需要定義圓括號。
  • 可選的大括號:如果主體包含了一個語句,就不需要使用大括號。
  • 可選的返回關鍵字:如果主體只有一個表達式返回值則編譯器會自動返回值,大括號需要指定明表達式返回了一個數值。

以下是一些簡單的例子,便於我們理解這些特性:

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

        // 2. 接收一個參數,()可以省略,返回其2倍的值
        x -> 2 * x

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

        
// 4. 接收2個int型整數,返回他們的和 ( int x, int y) ->x + y // 5. 接受一個 string 對象,並在控制臺打印,不返回任何值(看起來像是返回void) (String s) ->System.out.print(s)

二、lambda表達式使用

2.1、在for循環中使用

package com.my.controller;

import junit.framework.TestCase;
import org.junit.Test;

import java.util.ArrayList;
import java.util.List; /** * description:{description} * author:jyy * date:2018-01-09 16:43 * modify:{modify} */ public class AppTest extends TestCase { @Test public void test() { List<String> list = new ArrayList<>(); list.add("北京"); list.add("上海"); list.add("廣州"); list.add("深圳"); for (String str : list) { System.out.println(str); } System.out.println("================="); list.forEach(str -> System.out.println(str)); } }

執行結果:

北京
上海
廣州
深圳
=================
北京
上海
廣州
深圳

2.2、替代匿名內部類使用

我們使用JAVA基礎知識|內部類中的try catch示例

package com.my.controller;

import junit.framework.TestCase;
import org.junit.Test;

import java.util.ArrayList;
import java.util.List;

/**
 * description:{description}
 * author:jyy
 * date:2018-01-09 16:43
 * modify:{modify}
 */
public class AppTest extends TestCase {

    @Test
    public void test() {

        //匿名內部類
        new ExceptionTemplate().execute(new CatchExceptionable() {
            @Override
            public void catchException() {
                System.out.println("代碼");
            }
        });

        //lambda表達式
        new ExceptionTemplate().execute(() -> System.out.println("代碼"));
    }

}

2.3、lambda表達式與Comparator類結合使用

package com.my.controller;

import junit.framework.TestCase;
import org.junit.Test;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;

/**
 * description:{description}
 * author:jyy
 * date:2018-01-09 16:43
 * modify:{modify}
 */
public class AppTest extends TestCase {

    @Test
    public void test() {

        List<String> list = new ArrayList<>();
        list.add("BeiJing");
        list.add("ShangHai");
        list.add("GuangZhou");
        list.add("ShenZhen");

        list.sort(new Comparator<String>() {
            @Override
            public int compare(String o1, String o2) {
                return o1.compareTo(o2);
            }
        });
        list.forEach(str -> System.out.println(str));

        System.out.println("==============");

        List<String> list2 = new ArrayList<>();
        list2.add("BeiJing");
        list2.add("ShangHai");
        list2.add("GuangZhou");
        list2.add("ShenZhen");

        //list2.sort((String o1,String o2) -> o1.compareTo(o2));
        Comparator<String> comparator =(String o1,String o2) -> o1.compareTo(o2);
        list2.sort(comparator);
        list2.forEach(str -> System.out.println(str));

    }
}

執行結果:

BeiJing
GuangZhou
ShangHai
ShenZhen
==============
BeiJing
GuangZhou
ShangHai
ShenZhen

三、流stream

Java 8 中的stream 是對集合(Collection)對象功能的增強,它專註於對集合對象進行各種非常便利、高效的聚合操作(aggregate operation),或者大批量數據操作 (bulk data operation)。stream API 借助於同樣新出現的 lambda 表達式,極大的提高編程效率和程序可讀性。同時它提供串行和並行兩種模式進行匯聚操作,並發模式能夠充分利用多核處理器的優勢

生成流的兩種方式:

  • stream() ? 為集合創建串行流。
  • parallelStream() ? 為集合創建並行流。

下面我們就來使用stream提供的各種API:

3.1、篩選和切片

方法 描述
filter 從流中過濾元素
distinct 通過流所生成的元素的hashCode()和equals()方法去重
limit 截斷流,選取前n個元素
skip 跳過元素,返回一個扔掉了前 n 個元素的流。若流中元素不足n個,則返回一個空流

技術分享圖片
package com.my.po;

/**
 * description:{description}
 * author:jyy
 * date:2018-02-11 11:06
 * modify:{modify}
 */
public class Employee {
    private String id;
    private String name;
    private double salary;
    private String sex;

    public Employee(String id, String name, double salary,String sex) {
        this.id = id;
        this.name = name;
        this.salary = salary;
        this.sex=sex;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public double getSalary() {
        return salary;
    }

    public void setSalary(double salary) {
        this.salary = salary;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    @Override
    public String toString() {
        return "Employee{" +
                "id=‘" + id + ‘\‘‘ +
                ", name=‘" + name + ‘\‘‘ +
                ", salary=" + salary +
                ", sex=‘" + sex + ‘\‘‘ +
                ‘}‘;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        Employee employee = (Employee) o;

        return id.equals(employee.id);
    }

    @Override
    public int hashCode() {
        return id.hashCode();
    }
}
View Code 技術分享圖片
package com.my.controller;

import com.my.po.Employee;
import junit.framework.TestCase;
import org.junit.Test;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;

/**
 * description:{description}
 * author:jyy
 * date:2018-01-09 16:43
 * modify:{modify}
 */
public class AppTest extends TestCase {

    @Test
    public void test() {
        Employee[] employees = {
                new Employee("1001", "李明", 5000, "male"),
                new Employee("1002", "王明", 7000, "male"),
                new Employee("1003", "張麗", 10000, "female"),
                new Employee("1004", "謝楠", 11000, "female"),
                new Employee("1004", "謝楠", 11000, "female")
        };
        List<Employee> list = Arrays.asList(employees);

        //forEach,查詢所有數據
        list.stream().forEach(e -> System.out.println(e.toString()));

        //filter,查詢集合中所有的女性
        list.stream().filter(e -> Objects.equals(e.getSex(), "female")).forEach(e -> System.out.println(e.toString()));
        //查詢集合中薪資大於6000的雇員
        list.stream().filter(e -> e.getSalary() > 7000).forEach(e -> System.out.println(e));

        //limit,查詢前兩條數據
        list.stream().limit(2).forEach(e -> System.out.println(e.toString()));

        //distinct,去重,利用Employee對象中的hashCode()和equals()方法
        list.stream().distinct().forEach(e -> System.out.println(e));

        //skip,跳過前兩個
        list.stream().skip(2).forEach(e -> System.out.println(e));

    }
}
View Code

3.2、映射

方法 描述
map(Function f) 接受一個函數作為參數,並將函數應用到每一個元素上,返回新的元素
mapToDouble(ToDoubleFunction f) 返回的新元素為double類型
mapToInt(ToIntFunction f) 返回的新元素為int類型
mapToLong(ToLongFunction f) 返回的新元素為long類型
flatMap(Function f) 操作多層嵌套的流,使其扁平化

3.2.1、map

        Employee[] employees = {
                new Employee("1001", "李明", 5000, "male"),
                new Employee("1002", "王明", 7000, "male"),
                new Employee("1003", "張麗", 10000, "female"),
                new Employee("1004", "謝楠", 11000, "female"),
                new Employee("1004", "謝楠", 11000, "female")
        };
        List<Employee> list = Arrays.asList(employees);

        //map
        list.stream().map(e -> e.getSalary()).forEach(e -> System.out.println(e));

執行結果:

5000.0
7000.0
10000.0
11000.0
11000.0

可以看出,集合list經過map操作之後,類型已經改變。具體什麽類型,由返回值決定

3.2.2、mapToDouble、mapToInt、mapToLong

        Employee[] employees = {
                new Employee("1001", "李明", 5000, "male"),
                new Employee("1002", "王明", 7000, "male"),
                new Employee("1003", "張麗", 10000, "female"),
                new Employee("1004", "謝楠", 11000, "female"),
                new Employee("1004", "謝楠", 11000, "female")
        };
        List<Employee> list = Arrays.asList(employees);
        
        list.stream().mapToDouble(e -> e.getSalary()).forEach(e -> System.out.println(e));

執行結果:

5000.0
7000.0
10000.0
11000.0
11000.0

3.2.3、flatMap

        Employee[] employees1 = {
                new Employee("1001", "李明", 5000, "male"),
                new Employee("1002", "王明", 7000, "male"),
                new Employee("1003", "張麗", 10000, "female"),
                new Employee("1004", "謝楠", 11000, "female")
        };
        Employee[] employees2 = {
                new Employee("1005", "Marry", 5000, "male"),
                new Employee("1006", "Linda", 7000, "male"),
                new Employee("1007", "Cris", 10000, "female")
        };
        List<Employee[]> list = new ArrayList<>();
        list.add(employees1);
        list.add(employees2);
        list.stream().flatMap(e -> Arrays.stream(e)).forEach(e -> System.out.println(e.toString()));

執行結果:

Employee{id=‘1001‘, name=‘李明‘, salary=5000.0, sex=‘male‘}
Employee{id=‘1002‘, name=‘王明‘, salary=7000.0, sex=‘male‘}
Employee{id=‘1003‘, name=‘張麗‘, salary=10000.0, sex=‘female‘}
Employee{id=‘1004‘, name=‘謝楠‘, salary=11000.0, sex=‘female‘}
Employee{id=‘1005‘, name=‘Marry‘, salary=5000.0, sex=‘male‘}
Employee{id=‘1006‘, name=‘Linda‘, salary=7000.0, sex=‘male‘}
Employee{id=‘1007‘, name=‘Cris‘, salary=10000.0, sex=‘female‘}

JAVA基礎知識|lambda與stream