OptionalDouble, OptionalInt, and OptionalLong

Optional class is introduced in Java 8 as a container object which may or may not contain a non-null value. Together with Optional, there are three more container classes that added to contain primitive values of double, int, and long. They are:

  • OptionalDouble: A container object which may or may not contain a double value.
  • OptionalInt: A container object which may or may not contain an int value.
  • OptionalLong: A container object which may or may not contain a long value.

Same as Optional, these three classes also evolving from their release in Java 8, until now (Java 11). Additional methods are added, which is share similarity with their sister class, Optional. For references, please check previous article about Java 8 Optional and it's current features.

This article we give you an introduction and guides about OptionalDouble, OptionalInt, and OptionalLong

OptionalDouble Example

OptionalDouble is a container object which may or may not contain a double value. If a value is present, isPresent() returns true. If no value is present, the object is considered empty and isPresent() returns false.

The double data type is a double-precision 64-bit IEEE 754 floating point. Its range of values is specified in the Floating-Point Types, Formats, and Values section of the Java Language Specification. For decimal values, this data type is generally the default choice. This data type should never be used for precise values, such as currency.

OptionalDoubleExample.java
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.OptionalDouble;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class OptionalDoubleExample {

    public static void main(String[] args) {
        OptionalDouble optionalDouble = OptionalDouble.of(8.88);
        System.out.println(8.88 == optionalDouble.getAsDouble());
        
        optionalDouble = OptionalDouble.empty();
        System.out.println(optionalDouble.orElse(9.99));
        
        List<OptionalDouble> doubles = Arrays.asList(
                OptionalDouble.of(1.01),
                OptionalDouble.of(2.12),
                OptionalDouble.of(8.88),
                OptionalDouble.of(9.99)
        );

        List<Double> list1 = doubles.stream()
                .map(OptionalDouble::getAsDouble)
                .collect(Collectors.toList());
        System.out.println(list1);

        List<OptionalDouble> otherDoubles = new ArrayList<>();
        otherDoubles.addAll(doubles);
        otherDoubles.addAll(Arrays.asList(OptionalDouble.empty()));
        
        List<Double> list2 = otherDoubles.stream()
                .filter(OptionalDouble::isPresent)
                .filter(o -> o.getAsDouble() > 5.05)
                .map(OptionalDouble::getAsDouble)
                .collect(Collectors.toList());
        System.out.println(list2);

        List<String> list3 = otherDoubles.stream()
                .flatMap(o -> o.isPresent() ? Stream.of(o.getAsDouble()) : Stream.of(Double.valueOf("5.05")))
                .map(d -> Double.toString(d))
                .collect(Collectors.toList());
        System.out.println(list3);        
        
        Double d = doubles.stream().findFirst()
                .orElse(OptionalDouble.of(5.05)).getAsDouble();
        System.out.println(d);
    }
}
                    

true 9.99 [1.01, 2.12, 8.88, 9.99] [8.88, 9.99] [1.01, 2.12, 8.88, 9.99, 5.05] 1.01

OptionalInt Example

OptionalInt is a container object which may or may not contain an int value. If a value is present, isPresent() returns true. If no value is present, the object is considered empty and isPresent() returns false.

By default, the int data type is a 32-bit signed two's complement integer, which has a minimum value of -231 and a maximum value of 231-1. In Java SE 8 and later, you can use the int data type to represent an unsigned 32-bit integer, which has a minimum value of 0 and a maximum value of 232-1.

OptionalIntExample.java
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.OptionalInt;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class OptionalIntExample {

    public static void main(String[] args) {
        OptionalInt optionalInt = OptionalInt.of(888);
        System.out.println(888 == optionalInt.getAsInt());
        
        optionalInt = OptionalInt.empty();
        System.out.println(optionalInt.orElse(999));
        
        List<OptionalInt> integers = Arrays.asList(
                OptionalInt.of(101),
                OptionalInt.of(212),
                OptionalInt.of(888),
                OptionalInt.of(999)
        );

        List<Integer> list1 = integers.stream()
                .map(OptionalInt::getAsInt)
                .collect(Collectors.toList());
        System.out.println(list1);

        List<OptionalInt> otherInts = new ArrayList<>();
        otherInts.addAll(integers);
        otherInts.addAll(Arrays.asList(OptionalInt.empty()));
        
        List<Integer> list2 = otherInts.stream()
                .filter(OptionalInt::isPresent)
                .filter(o -> o.getAsInt() > 500)
                .map(OptionalInt::getAsInt)
                .collect(Collectors.toList());
        System.out.println(list2);

        List<String> list3 = otherInts.stream()
                .flatMap(o -> o.isPresent() ? Stream.of(o.getAsInt()) : Stream.of(Integer.valueOf("500")))
                .map(i -> Integer.toString(i))
                .collect(Collectors.toList());
        System.out.println(list3);        
        
        Integer i = integers.stream().findFirst()
                .orElse(OptionalInt.of(500)).getAsInt();
        System.out.println(i);
    }
}
                    

true 999 [101, 212, 888, 999] [888, 999] [101, 212, 888, 999, 500] 101

OptionalLong Example

OptionalLong is a container object which may or may not contain a long value. If a value is present, isPresent() returns true. If no value is present, the object is considered empty andisPresent() returns false.

The long data type is a 64-bit two's complement integer. The signed long has a minimum value of -263 and a maximum value of 263-1. In Java SE 8 and later, you can use the long data type to represent an unsigned 64-bit long, which has a minimum value of 0 and a maximum value of 264-1. Use this data type when you need a range of values wider than those provided by int.

OptionalLongExample.java
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.OptionalLong;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class OptionalLongExample {

    public static void main(String[] args) {
        OptionalLong optionalLong = OptionalLong.of(2147483648l);
        System.out.println(2147483648l == optionalLong.getAsLong());
        
        optionalLong = OptionalLong.empty();
        System.out.println(optionalLong.orElse(2147484646l));
        
        List<OptionalLong> longs = Arrays.asList(
                OptionalLong.of(2147483748l),
                OptionalLong.of(2147483859l),
                OptionalLong.of(2147484535l),
                OptionalLong.of(2147484646l)
        );

        List<Long> list1 = longs.stream()
                .map(OptionalLong::getAsLong)
                .collect(Collectors.toList());
        System.out.println(list1);

        List<OptionalLong> otherLongs = new ArrayList<>();
        otherLongs.addAll(longs);
        otherLongs.addAll(Arrays.asList(OptionalLong.empty()));
        
        List<Long> list2 = otherLongs.stream()
                .filter(OptionalLong::isPresent)
                .filter(o -> o.getAsLong() > 2147484147l)
                .map(OptionalLong::getAsLong)
                .collect(Collectors.toList());
        System.out.println(list2);

        List<String> list3 = otherLongs.stream()
                .flatMap(o -> o.isPresent() ? Stream.of(o.getAsLong()) : Stream.of(Long.MAX_VALUE))
                .map(l -> Long.toString(l))
                .collect(Collectors.toList());
        System.out.println(list3);
        
        
        Long l = longs.stream().findFirst()
                .orElse(OptionalLong.of(Long.MAX_VALUE)).getAsLong();
        System.out.println(l);
    }
}
                    

true 2147484646 [2147483748, 2147483859, 2147484535, 2147484646] [2147484535, 2147484646] [2147483748, 2147483859, 2147484535, 2147484646, 9223372036854775807] 2147483748

Conclusion

Java Optional, and its three Optional for primitive friends, is very useful when used as a return type from an operation where previously you might have returned null.