網頁

2019/10/23

Java Lambda 把元素為Optional的List轉為另一個List
covert List<Optional<Object>> to another List

Java 8 Lambda Stream collect 排除 null 元素List中的元素為一般的物件,若List中的元素為Optional包裝的物件,且有部分可能是Optional.empty()的情況,蒐集元素中某個屬性轉換成另一個List的寫法如下。


例如下面範例有個List裡面裝的是被Optional包裝的Employee物件,如果要排除空元素及Employee.name == null的lambda的寫法如下。

package com.abc.demo;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

import org.apache.commons.lang3.StringUtils;

public class Main {

    public static void main(String[] args) {
       
        List<Optional<Employee>> employeeOptList = new ArrayList<>(); // 一個List,裡面裝有Optional<Empoyee>,可能是資料庫傳回的東西。
        employeeOptList.add(Optional.ofNullable(new Employee(1L, "Ann")));
        employeeOptList.add(Optional.ofNullable(new Employee(2L, "Jin")));
        employeeOptList.add(Optional.ofNullable(new Employee(3L, null)));
        employeeOptList.add(Optional.ofNullable(new Employee(4L, "Ken")));
        employeeOptList.add(Optional.ofNullable(null));
        
        List<String> nameList1 = employeeOptList.stream()
                .filter(Optional::isPresent) // 過濾掉Optional.empty()的元素
                .map(Optional::get) // 經過filter的過濾,這邊的元素不會是Optional.empty(),所以可以放心呼叫get()
                .map(Employee::getName) // 取得Employee.name
                .filter(StringUtils::isNotEmpty) // 排除Employe.name 為空的情況
                .collect(Collectors.toList()); // 把Employee.name蒐集成List<String>
        
        nameList1.forEach(System.out::println);
        
        System.out.println("------------------------------------");

        List<String> nameList2 = employeeOptList.stream()
                .flatMap(Optional::stream) // Java 9 Optional.stream()
                .map(Employee::getName)
                .filter(StringUtils::isNotEmpty)
                .collect(Collectors.toList()); 
        
        nameList2.forEach(System.out::println);
        
    }
 
}

class Employee {
    
    private Long id;
    private String name;
    
    public Employee(Long id, String name) {
        this.id = id;
        this.name = name;
    }

    // getters and setters
    
}

印出的結果如下。

Ann
Jin
Ken
------------------------------------
Ann
Jin
Ken

Optional.stream()原始碼如下。
若元素為Optional.empty()返回Stream.empty(),反之返回Stream.of(value)

public Stream<T> stream() {
    if (!isPresent()) {
        return Stream.empty();
    } else {
        return Stream.of(value);
    }
}

沒有留言:

張貼留言