Total Pageviews

2016/11/10

[Java 8] Optional

Assume I have a List of project:
1
2
3
 OptionalTest.Project(id=1, name=FMS)
 OptionalTest.Project(id=1, name=NSS)
 OptionalTest.Project(id=1, name=DBM)

If we use a non-existing project name to do search, it will throw java.lang.NullPointerException
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
@Slf4j
public class OptionalTest {

    public static void main(String[] args) {
        OptionalTest test = new OptionalTest();        

        Project test1 = test.getProjectByName("test");
        log.debug("test1 = " + test1.toString());
    }
    

    private Project getProjectByName(String name) {
        return getProjects().stream().filter(p -> p.getName().equals(name)).findAny().orElse(null);
    }
}

Therefore, we need to add if-else statement to stay away from java.lang.NullPointerException
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
@Slf4j
public class OptionalTest {

    public static void main(String[] args) {
        OptionalTest test = new OptionalTest();
        Project test1 = test.getProjectByName("test");
        if (test1 != null) {
            log.debug("test1 = " + test1.toString());
        } else {
            throw new RuntimeException("無資料");
        }
    }
    
    private Project getProjectByName(String name) {
        return getProjects().stream().filter(p -> p.getName().equals(name)).findAny().orElse(null);
    }
}

Optional is a container object which is used to contain not-null objects. Optional object is used to represent null with absent value. This class has various utility methods to facilitate code to handle values as ‘available’ or ‘not available’ instead of checking null values. It is introduced in Java 8 and is similar to what Optional is in Guava.

For example, it will return Optional instead of Project in getProjectByNameWithOptional method. Owing to using Optional, if you find nothing it will throw java.util.NoSuchElementException: No value present
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
@Slf4j
public class OptionalTest {

    public static void main(String[] args) {
        OptionalTest test = new OptionalTest();

        Project test2 = test.getProjectByNameWithOptional("test").get();
        log.debug("test2 = " + test2.toString());
    }
    

    private Project getProjectByName(String name) {
        return getProjects().stream().filter(p -> p.getName().equals(name)).findAny().orElse(null);
    }

    private Optional<Project> getProjectByNameWithOptional(String name) {
        Optional<Project> project = Optional.ofNullable(getProjects().stream()
                .filter(p -> p.getName().equals(name)).findAny().orElse(null));
        return project;
    }
}    


If you would like use customized error message instead of java.util.NoSuchElementException: No value present, you can do this way:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
@Slf4j
public class OptionalTest {

    public static void main(String[] args) {
        OptionalTest test = new OptionalTest();

        Project test2 = test.getProjectByNameWithOptional("test").get();
        log.debug("test2 = " + test2.toString());
    }
    

    private Project getProjectByName(String name) {
        return getProjects().stream().filter(p -> p.getName().equals(name)).findAny().orElse(null);
    }

    private Optional<Project> getProjectByNameWithOptional(String name) {
        Optional<Project> project = Optional.ofNullable(getProjects().stream()
                .filter(p -> p.getName().equals(name)).findAny().orElse(null));
        project.orElseThrow(() -> new RuntimeException("查無資料"));
        return project;
    }
}

Reference
[1] https://docs.oracle.com/javase/8/docs/api/java/util/Optional.html

No comments: