Java 8 Optional

Java 8 đã giới thiệu một lớp mới là Optional trong package java.util. Nó được sử dụng để đại diện cho một giá trị có mặt hoặc vắng mặt. Lợi ích chính của cấu trúc mới này là Không có quá nhiều kiểm tra null và tránh bất kỳ NullPointerExceptions xảy ra trong runtime. Do dó Optional hỗ trợ phát triển các API hoặc ứng dụng Java gọn gàng. Giống Collections và arrays, nó cũng là một Container để chứa tối đa một giá trị. Chúng ta hãy cùng khám phá cấu trúc mới này bằng một số ví dụ hữu ích sau đây.

Ưu điểm của Java 8 Optional:

  • Không bắt buộc kiểm tra Null.
  • Tránh NullPointerException ở runtime.
  • Hỗ trợ phát triển các API một cách gọn gàng.

1. Ví dụ cơ bản về Java 8 Optional

Phương thức Optional.ofNullable() trả về một Non-empty Optional nếu giá trị hiện hữu, ngược lại sẽ trả về một empty Optional. Phương thức Optional.empty() tạo một đối tượng empty Optional.

package vuta.test;

import java.util.Optional;

public class OptionalBasicExample {

    public static void main(String[] args) {

        Optional<String> gender = Optional.of("MALE");
        String answer1 = "Yes";
        String answer2 = null;

        System.out.println("Non-Empty Optional:" + gender);
        System.out.println("Non-Empty Optional: Gender value : " + gender.get());
        System.out.println("Empty Optional: " + Optional.empty());

        System.out.println("ofNullable on Non-Empty Optional: " + Optional.ofNullable(answer1));
        System.out.println("ofNullable on Empty Optional: " + Optional.ofNullable(answer2));

    }

}

Output

Non-Empty Optional:Optional[MALE] Non-Empty Optional: Gender value : MALE Empty Optional: Optional.empty

ofNullable on Non-Empty Optional: Optional[Yes] ofNullable on Empty Optional: Optional.empty

2. Optional.map and flatMap

package vuta.test;

import java.util.Optional;

public class OptionalMapFlapMapExample {

    public static void main(String[] args) {

        Optional<String> nonEmptyGender = Optional.of("male");
        Optional<String> emptyGender = Optional.empty();

        System.out.println("Non-Empty Optional:: " + nonEmptyGender.map(String::toUpperCase));
        System.out.println("Empty Optional    :: " + emptyGender.map(String::toUpperCase));

        Optional<Optional<String>> nonEmptyOtionalGender = Optional.of(Optional.of("male"));
        System.out.println("Optional value   :: " + nonEmptyOtionalGender);
        System.out.println("Optional.map     :: " + nonEmptyOtionalGender.map(gender -> gender.map(String::toUpperCase)));
        System.out.println("Optional.flatMap :: " + nonEmptyOtionalGender.flatMap(gender -> gender.map(String::toUpperCase)));

    }

}

Output

Non-Empty Optional:: Optional[MALE] Empty Optional :: Optional.empty Optional value :: Optional[Optional[male]] Optional.map :: Optional[Optional[MALE]] Optional.flatMap :: Optional[MALE]

3. Optional.filter

package vuta.test;

import java.util.Optional;

public class OptionalFilterExample {

    public static void main(String[] args) {

        Optional<String> gender = Optional.of("MALE");
        Optional<String> emptyGender = Optional.empty();

        //Filter on Optional
        System.out.println(gender.filter(g -> g.equals("male"))); //Optional.empty
        System.out.println(gender.filter(g -> g.equalsIgnoreCase("MALE"))); //Optional[MALE]
        System.out.println(emptyGender.filter(g -> g.equalsIgnoreCase("MALE"))); //Optional.empty

    }

}

Output

Optional.empty Optional[MALE] Optional.empty

4. Optional isPresent và ifPresent

Optional.isPresent() trả về true nếu đối tượng Optional khác rỗng, ngược lại trả về false. Optional.ifPresent() thực thi action nếu đối tượng Optional khác rỗng, ngược lại trả về false.

package vuta.test;

import java.util.Optional;

public class OptionalIfPresentExample {

    public static void main(String[] args) {

        Optional<String> gender = Optional.of("MALE");
        Optional<String> emptyGender = Optional.empty();

        if (gender.isPresent()) {
            System.out.println("Value available.");
        } else {
            System.out.println("Value not available.");
        }

        gender.ifPresent(g -> System.out.println("In gender Option, value available."));

        //condition failed, no output print
        emptyGender.ifPresent(g -> System.out.println("In emptyGender Option, value available."));

    }

}

Output

Value available. In gender Option, value available.

5. Optional orElse

package vuta.test;

import java.util.Optional;

public class OptionalOrElseExample {

    public static void main(String[] args) {

        Optional<String> gender = Optional.of("MALE");
        Optional<String> emptyGender = Optional.empty();

        System.out.println(gender.orElse("<N/A>")); //MALE
        System.out.println(emptyGender.orElse("<N/A>")); //<N/A>

        System.out.println(gender.orElseGet(() -> "<N/A>")); //MALE
        System.out.println(emptyGender.orElseGet(() -> "<N/A>")); //<N/A>

    }

}

Output

MALE <N/A> MALE <N/A>

6. Ví dụ khi không dùng Java 8 Optional

package vuta.test;

public class ScreenResolution {

	private int width;
	private int height;

	public ScreenResolution(int width, int height){
		this.width = width;
		this.height = height;
	}

	public int getWidth() {
		return width;
	}

	public int getHeight() {
		return height;
	}

}
package vuta.test;

public class DisplayFeatures {

	private String size; // In inches
	private ScreenResolution resolution;

	public DisplayFeatures(String size, ScreenResolution resolution){
		this.size = size;
		this.resolution = resolution;
	}

	public String getSize() {
		return size;
	}
	public ScreenResolution getResolution() {
		return resolution;
	}

}
package vuta.test;

public class Mobile {

	private long id;
	private String brand;
	private String name;
	private DisplayFeatures displayFeatures;

	public Mobile(long id, String brand, String name,
                            DisplayFeatures displayFeatures){
		this.id = id;
		this.brand = brand;
		this.name = name;
		this.displayFeatures = displayFeatures;
	}

	public long getId() {
		return id;
	}

	public String getBrand() {
		return brand;
	}

	public String getName() {
		return name;
	}

	public DisplayFeatures getDisplayFeatures() {
		return displayFeatures;
	}

}
package vuta.test;

public class MobileService {

	public int getMobileScreenWidth(Mobile mobile){

        //Check null, check null and check null :(
		if(mobile != null){
			DisplayFeatures dfeatures = mobile.getDisplayFeatures();
			if(dfeatures != null){
				ScreenResolution resolution = dfeatures.getResolution();
				if(resolution != null){
					return resolution.getWidth();
				}
			}
		}
		return 0;

	}

}

7. Ốp Java 8 Optional vào

package vuta.test;

import java.util.Optional;

public class DisplayFeatures {

	private String size; // Inches
	private Optional<ScreenResolution> resolution;

	public DisplayFeatures(String size, Optional<ScreenResolution> resolution){
		this.size = size;
		this.resolution = resolution;
	}

	public String getSize() {
		return size;
	}
	public Optional<ScreenResolution> getResolution() {
		return resolution;
	}

}
package vuta.test;

import java.util.Optional;

public class Mobile {

	private long id;
	private String brand;
	private String name;
	private Optional<DisplayFeatures> displayFeatures;

	public Mobile(long id, String brand, String name, Optional<DisplayFeatures> displayFeatures){
		this.id = id;
		this.brand = brand;
		this.name = name;
		this.displayFeatures = displayFeatures;
	}

	public long getId() {
		return id;
	}

	public String getBrand() {
		return brand;
	}

	public String getName() {
		return name;
	}

	public Optional<DisplayFeatures> getDisplayFeatures() {
		return displayFeatures;
	}

}
package vuta.test;

import java.util.Optional;

public class MobileService {

  public Integer getMobileScreenWidth(Optional<Mobile> mobile){
    //ngon
	return mobile.flatMap(Mobile::getDisplayFeatures)
		 .flatMap(DisplayFeatures::getResolution)
		 .map(ScreenResolution::getWidth)
		 .orElse(0);

  }

}

All Rights Reserved