1 /* 2 * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 package java.util; 26 27 import java.util.function.IntConsumer; 28 import java.util.function.IntSupplier; 29 import java.util.function.Supplier; 30 31 /** 32 * A container object which may or may not contain a {@code int} value. 33 * If a value is present, {@code isPresent()} will return {@code true} and 34 * {@code get()} will return the value. 35 * 36 * <p>Additional methods that depend on the presence or absence of a contained 37 * value are provided, such as {@link #orElse(java.lang.Object) orElse()} 38 * (return a default value if value not present) and 39 * {@link #ifPresent(java.util.function.Consumer) ifPresent()} (execute a block 40 * of code if the value is present.) 41 * 42 * @since 1.8 43 */ 44 public final class OptionalInt { 45 /** 46 * Common instance for {@code empty()}. 47 */ 48 private final static OptionalInt EMPTY = new OptionalInt(); 49 50 /** 51 * If true then the value is present, otherwise indicates no value is present 52 */ 53 private final boolean isPresent; 54 private final int value; 55 56 /** 57 * Construct a non-empty instance 58 * 59 * @param value the int value to be present. 60 */ 61 private OptionalInt(int value) { 62 this.isPresent = true; 63 this.value = value; 64 } 65 66 /** 67 * Construct an empty instance. 68 * 69 * @implNote generally only one empty instance, {@link OptionalInt#EMPTY}, 70 * should exist per VM. 71 */ 72 private OptionalInt() { 73 this.isPresent = false; 74 this.value = 0; 75 } 76 77 /** 78 * Return an empty {@code OptionalInt}. No value is present for this Optional. 79 * 80 * @apiNote Though it may be tempting to do so, avoid testing if an object 81 * is empty by comparing with {@code ==} against instances returned 82 * {@code Option.empty()}. There is no guarantee that it is a singleton. 83 * Instead, use {@code isPresent()}. 84 * 85 * @return an empty {@code OptionalInt}. 86 */ 87 @SuppressWarnings("unchecked") 88 public static OptionalInt empty() { 89 return EMPTY; 90 } 91 92 /** 93 * Create a new {@code OptionalInt} with a present value 94 * @param value The int value 95 * @param value new {@code OptionalInt} with a present value. 96 */ 97 public static OptionalInt of(int value) { 98 return new OptionalInt(value); 99 } 100 101 /** 102 * If a value is present in this {@code OptionalInt}, returns the value, 103 * otherwise throws {@code NoSuchElementException}. 104 * 105 * @return the value held by this {@code OptionalInt}. 106 * @throws NoSuchElementException if there is no value present. 107 * 108 * @see OptionalInt#isPresent() 109 */ 110 public int getAsInt() { 111 if (!isPresent) { 112 throw new NoSuchElementException("No value present"); 113 } 114 return value; 115 } 116 117 /** 118 * Return {@code true} if there is a value present, otherwise {@code false}. 119 * 120 * @return {@code true} if there is a value present, otherwise {@code false}. 121 */ 122 public boolean isPresent() { 123 return isPresent; 124 } 125 126 /** 127 * Execute the specified consumer with the value if a value is present, 128 * otherwise do nothing. 129 * 130 * @param consumer block to be executed if a value is present. 131 * @throws NullPointerException if value is present and {@code consumer} is 132 * null. 133 */ 134 public void ifPresent(IntConsumer consumer) { 135 if (isPresent) 136 consumer.accept(value); 137 } 138 139 /** 140 * Return the value if present, otherwise return {@code other}. 141 * 142 * @param other value to be returned if there is no value present. 143 * @return the value, if present, otherwise {@code other}. 144 */ 145 public int orElse(int other) { 146 return isPresent ? value : other; 147 } 148 149 /** 150 * Return the value if present, otherwise invoke {@code other} and return 151 * the result of that invocation. 152 * 153 * @param other {@code IntSupplier} who's result is returned if there is no 154 * value present. 155 * @return the value if present otherwise return result of {@code other}. 156 * @throws NullPointerException if value is absent and {@code other} is null. 157 */ 158 public int orElseGet(IntSupplier other) { 159 return isPresent ? value : other.getAsInt(); 160 } 161 162 /** 163 * Return the contained value, if present, otherwise throw an exception 164 * to be created by the provided supplier. 165 * 166 * @param <V> Type of the exception to be thrown. 167 * @param exceptionSupplier The supplier which will return the exception to 168 * be thrown. 169 * @return the value. 170 * @throws V if there is no value present. 171 * @throws NullPointerException if value is absent and 172 * {@code exceptionSupplier} is null. 173 */ 174 public<V extends Throwable> int orElseThrow(Supplier<V> exceptionSupplier) throws V { 175 if (isPresent) { 176 return value; 177 } else { 178 throw exceptionSupplier.get(); 179 } 180 } 181 182 @Override 183 public boolean equals(Object o) { 184 if (this == o) { 185 return true; 186 } 187 188 if (!(o instanceof OptionalInt)) { 189 return false; 190 } 191 192 OptionalInt other = (OptionalInt) o; 193 return (isPresent && other.isPresent) ? value == other.value : isPresent == other.isPresent; 194 } 195 196 @Override 197 public int hashCode() { 198 return Integer.hashCode(value); 199 } 200 201 @Override 202 public String toString() { 203 return isPresent 204 ? String.format("IntOptional[%s]", value) 205 : "IntOptional.empty"; 206 } 207 }