# HG changeset patch
# User psandoz
# Date 1423822407 -3600
# Node ID 8498cdb7c54bf65f03765630abf377a1af69aa36
# Parent  e3028445a1ffce6fcce68b12b75f42f1fe0d72e9
8071670: java.util.Optional: please add a way to specify if-else behavior
Reviewed-by: dfuchs, lowasser

diff -r e3028445a1ff -r 8498cdb7c54b jdk/src/java.base/share/classes/java/util/Optional.java
--- a/jdk/src/java.base/share/classes/java/util/Optional.java	Fri Feb 13 11:03:57 2015 +0800
+++ b/jdk/src/java.base/share/classes/java/util/Optional.java	Fri Feb 13 11:13:27 2015 +0100
@@ -38,8 +38,8 @@
  * <p>Additional methods that depend on the presence or absence of a contained
  * value are provided, such as {@link #orElse(java.lang.Object) orElse()}
  * (return a default value if value not present) and
- * {@link #ifPresent(java.util.function.Consumer) ifPresent()} (execute a block
- * of code if the value is present).
+ * {@link #ifPresent(java.util.function.Consumer) ifPresent()} (perform an
+ * action if the value is present).
  *
  * <p>This is a <a href="../lang/doc-files/ValueBased.html">value-based</a>
  * class; use of identity-sensitive operations (including reference equality
@@ -148,16 +148,35 @@
     }
 
     /**
-     * If a value is present, invoke the specified consumer with the value,
+     * If a value is present, perform the given action with the value,
      * otherwise do nothing.
      *
-     * @param consumer block to be executed if a value is present
-     * @throws NullPointerException if value is present and {@code consumer} is
+     * @param action the action to be performed if a value is present
+     * @throws NullPointerException if a value is present and {@code action} is
      * null
      */
-    public void ifPresent(Consumer<? super T> consumer) {
+    public void ifPresent(Consumer<? super T> action) {
         if (value != null) {
-            consumer.accept(value);
+            action.accept(value);
+        }
+    }
+
+    /**
+     * If a value is present, perform the given action with the value,
+     * otherwise perform the given empty-based action.
+     *
+     * @param action the action to be performed if a value is present
+     * @param emptyAction the empty-based action to be performed if a value is
+     * not present
+     * @throws NullPointerException if a value is present and {@code action} is
+     * null, or a value is not present and {@code emptyAction} is null.
+     * @since 1.9
+     */
+    public void ifPresentOrElse(Consumer<? super T> action, Runnable emptyAction) {
+        if (value != null) {
+            action.accept(value);
+        } else {
+            emptyAction.run();
         }
     }
 
diff -r e3028445a1ff -r 8498cdb7c54b jdk/src/java.base/share/classes/java/util/OptionalDouble.java
--- a/jdk/src/java.base/share/classes/java/util/OptionalDouble.java	Fri Feb 13 11:03:57 2015 +0800
+++ b/jdk/src/java.base/share/classes/java/util/OptionalDouble.java	Fri Feb 13 11:13:27 2015 +0100
@@ -37,8 +37,8 @@
  * <p>Additional methods that depend on the presence or absence of a contained
  * value are provided, such as {@link #orElse(double) orElse()}
  * (return a default value if value not present) and
- * {@link #ifPresent(java.util.function.DoubleConsumer) ifPresent()} (execute a block
- * of code if the value is present).
+ * {@link #ifPresent(java.util.function.DoubleConsumer) ifPresent()} (perform an
+ * action if the value is present).
  *
  * <p>This is a <a href="../lang/doc-files/ValueBased.html">value-based</a>
  * class; use of identity-sensitive operations (including reference equality
@@ -131,16 +131,35 @@
     }
 
     /**
-     * Have the specified consumer accept the value if a value is present,
+     * If a value is present, perform the given action with the value,
      * otherwise do nothing.
      *
-     * @param consumer block to be executed if a value is present
-     * @throws NullPointerException if value is present and {@code consumer} is
+     * @param action the action to be performed if a value is present
+     * @throws NullPointerException if a value is present and {@code action} is
      * null
      */
-    public void ifPresent(DoubleConsumer consumer) {
+    public void ifPresent(DoubleConsumer action) {
         if (isPresent) {
-            consumer.accept(value);
+            action.accept(value);
+        }
+    }
+
+    /**
+     * If a value is present, perform the given action with the value,
+     * otherwise perform the given empty-based action.
+     *
+     * @param action the action to be performed if a value is present
+     * @param emptyAction the empty-based action to be performed if a value is
+     * not present
+     * @throws NullPointerException if a value is present and {@code action} is
+     * null, or a value is not present and {@code emptyAction} is null.
+     * @since 1.9
+     */
+    public void ifPresentOrElse(DoubleConsumer action, Runnable emptyAction) {
+        if (isPresent) {
+            action.accept(value);
+        } else {
+            emptyAction.run();
         }
     }
 
diff -r e3028445a1ff -r 8498cdb7c54b jdk/src/java.base/share/classes/java/util/OptionalInt.java
--- a/jdk/src/java.base/share/classes/java/util/OptionalInt.java	Fri Feb 13 11:03:57 2015 +0800
+++ b/jdk/src/java.base/share/classes/java/util/OptionalInt.java	Fri Feb 13 11:13:27 2015 +0100
@@ -37,8 +37,8 @@
  * <p>Additional methods that depend on the presence or absence of a contained
  * value are provided, such as {@link #orElse(int) orElse()}
  * (return a default value if value not present) and
- * {@link #ifPresent(java.util.function.IntConsumer) ifPresent()} (execute a block
- * of code if the value is present).
+ * {@link #ifPresent(java.util.function.IntConsumer) ifPresent()} (perform an
+ * action if the value is present).
  *
  * <p>This is a <a href="../lang/doc-files/ValueBased.html">value-based</a>
  * class; use of identity-sensitive operations (including reference equality
@@ -131,16 +131,35 @@
     }
 
     /**
-     * Have the specified consumer accept the value if a value is present,
+     * If a value is present, perform the given action with the value,
      * otherwise do nothing.
      *
-     * @param consumer block to be executed if a value is present
-     * @throws NullPointerException if value is present and {@code consumer} is
+     * @param action the action to be performed if a value is present
+     * @throws NullPointerException if value is present and {@code action} is
      * null
      */
-    public void ifPresent(IntConsumer consumer) {
+    public void ifPresent(IntConsumer action) {
         if (isPresent) {
-            consumer.accept(value);
+            action.accept(value);
+        }
+    }
+
+    /**
+     * If a value is present, perform the given action with the value,
+     * otherwise perform the given empty-based action.
+     *
+     * @param action the action to be performed if a value is present
+     * @param emptyAction the empty-based action to be performed if a value is
+     * not present
+     * @throws NullPointerException if a value is present and {@code action} is
+     * null, or a value is not present and {@code emptyAction} is null.
+     * @since 1.9
+     */
+    public void ifPresentOrElse(IntConsumer action, Runnable emptyAction) {
+        if (isPresent) {
+            action.accept(value);
+        } else {
+            emptyAction.run();
         }
     }
 
diff -r e3028445a1ff -r 8498cdb7c54b jdk/src/java.base/share/classes/java/util/OptionalLong.java
--- a/jdk/src/java.base/share/classes/java/util/OptionalLong.java	Fri Feb 13 11:03:57 2015 +0800
+++ b/jdk/src/java.base/share/classes/java/util/OptionalLong.java	Fri Feb 13 11:13:27 2015 +0100
@@ -37,8 +37,8 @@
  * <p>Additional methods that depend on the presence or absence of a contained
  * value are provided, such as {@link #orElse(long) orElse()}
  * (return a default value if value not present) and
- * {@link #ifPresent(java.util.function.LongConsumer) ifPresent()} (execute a block
- * of code if the value is present).
+ * {@link #ifPresent(java.util.function.LongConsumer) ifPresent()} (perform an
+ * action if the value is present).
  *
  * <p>This is a <a href="../lang/doc-files/ValueBased.html">value-based</a>
  * class; use of identity-sensitive operations (including reference equality
@@ -131,16 +131,35 @@
     }
 
     /**
-     * Have the specified consumer accept the value if a value is present,
+     * If a value is present, perform the given action with the value,
      * otherwise do nothing.
      *
-     * @param consumer block to be executed if a value is present
-     * @throws NullPointerException if value is present and {@code consumer} is
+     * @param action the action to be performed if a value is present
+     * @throws NullPointerException if a value is present and {@code action} is
      * null
      */
-    public void ifPresent(LongConsumer consumer) {
+    public void ifPresent(LongConsumer action) {
         if (isPresent) {
-            consumer.accept(value);
+            action.accept(value);
+        }
+    }
+
+    /**
+     * If a value is present, perform the given action with the value,
+     * otherwise perform the given empty-based action.
+     *
+     * @param action the action to be performed if a value is present
+     * @param emptyAction the empty-based action to be performed if a value is
+     * not present
+     * @throws NullPointerException if a value is present and {@code action} is
+     * null, or a value is not present and {@code emptyAction} is null.
+     * @since 1.9
+     */
+    public void ifPresentOrElse(LongConsumer action, Runnable emptyAction) {
+        if (isPresent) {
+            action.accept(value);
+        } else {
+            emptyAction.run();
         }
     }
 
diff -r e3028445a1ff -r 8498cdb7c54b jdk/test/java/util/Optional/Basic.java
--- a/jdk/test/java/util/Optional/Basic.java	Fri Feb 13 11:03:57 2015 +0800
+++ b/jdk/test/java/util/Optional/Basic.java	Fri Feb 13 11:13:27 2015 +0100
@@ -27,8 +27,12 @@
  * @run testng Basic
  */
 
+import java.lang.AssertionError;
+import java.lang.NullPointerException;
+import java.lang.Throwable;
 import java.util.NoSuchElementException;
 import java.util.Optional;
+import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.stream.Stream;
 
 import static org.testng.Assert.*;
@@ -51,7 +55,23 @@
         assertTrue(!empty.toString().isEmpty());
         assertTrue(!empty.toString().equals(presentEmptyString.toString()));
         assertTrue(!empty.isPresent());
-        empty.ifPresent(v -> { fail(); });
+
+        empty.ifPresent(v -> fail());
+
+        AtomicBoolean emptyCheck = new AtomicBoolean();
+        empty.ifPresentOrElse(v -> fail(), () -> emptyCheck.set(true));
+        assertTrue(emptyCheck.get());
+
+        try {
+            empty.ifPresentOrElse(v -> fail(), () -> { throw new ObscureException(); });
+            fail();
+        } catch (ObscureException expected) {
+        } catch (AssertionError e) {
+            throw e;
+        } catch (Throwable t) {
+            fail();
+        }
+
         assertSame(null, empty.orElse(null));
         RuntimeException orElse = new RuntimeException() { };
         assertSame(Boolean.FALSE, empty.orElse(Boolean.FALSE));
@@ -59,6 +79,31 @@
         assertSame(Boolean.FALSE, empty.orElseGet(() -> Boolean.FALSE));
     }
 
+    @Test(groups = "unit")
+    public void testIfPresentAndOrElseAndNull() {
+        Optional<Boolean> empty = Optional.empty();
+        Optional<Boolean> present = Optional.of(Boolean.TRUE);
+
+        // No NPE
+        present.ifPresentOrElse(v -> {}, null);
+        empty.ifPresent(null);
+        empty.ifPresentOrElse(null, () -> {});
+
+        // NPE
+        try {
+            present.ifPresent(null);
+            fail();
+        } catch (NullPointerException ex) {}
+        try {
+            present.ifPresentOrElse(null, () -> {});
+            fail();
+        } catch (NullPointerException ex) {}
+        try {
+            empty.ifPresentOrElse(v -> {}, null);
+            fail();
+        } catch (NullPointerException ex) {}
+    }
+
     @Test(expectedExceptions=NoSuchElementException.class)
     public void testEmptyGet() {
         Optional<Boolean> empty = Optional.empty();
@@ -102,12 +147,33 @@
         assertTrue(!present.toString().equals(presentEmptyString.toString()));
         assertTrue(-1 != present.toString().indexOf(Boolean.TRUE.toString()));
         assertSame(Boolean.TRUE, present.get());
+
+        AtomicBoolean presentCheck = new AtomicBoolean();
+        present.ifPresent(v -> presentCheck.set(true));
+        assertTrue(presentCheck.get());
+        presentCheck.set(false);
+        present.ifPresentOrElse(v -> presentCheck.set(true), () -> fail());
+        assertTrue(presentCheck.get());
+
         try {
             present.ifPresent(v -> { throw new ObscureException(); });
             fail();
         } catch (ObscureException expected) {
+        } catch (AssertionError e) {
+            throw e;
+        } catch (Throwable t) {
+            fail();
+        }
+        try {
+            present.ifPresentOrElse(v -> { throw new ObscureException(); }, () -> fail());
+            fail();
+        } catch (ObscureException expected) {
+        } catch (AssertionError e) {
+            throw e;
+        } catch (Throwable t) {
+            fail();
+        }
 
-        }
         assertSame(Boolean.TRUE, present.orElse(null));
         assertSame(Boolean.TRUE, present.orElse(Boolean.FALSE));
         assertSame(Boolean.TRUE, present.orElseGet(null));
diff -r e3028445a1ff -r 8498cdb7c54b jdk/test/java/util/Optional/BasicDouble.java
--- a/jdk/test/java/util/Optional/BasicDouble.java	Fri Feb 13 11:03:57 2015 +0800
+++ b/jdk/test/java/util/Optional/BasicDouble.java	Fri Feb 13 11:13:27 2015 +0100
@@ -29,6 +29,7 @@
 
 import java.util.NoSuchElementException;
 import java.util.OptionalDouble;
+import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.stream.DoubleStream;
 
 import static org.testng.Assert.*;
@@ -49,41 +50,82 @@
         assertTrue(0 == empty.hashCode());
         assertTrue(!empty.toString().isEmpty());
         assertTrue(!empty.isPresent());
+
         empty.ifPresent(v -> { fail(); });
+
+        AtomicBoolean emptyCheck = new AtomicBoolean();
+        empty.ifPresentOrElse(v -> fail(), () -> emptyCheck.set(true));
+        assertTrue(emptyCheck.get());
+
+        try {
+            empty.ifPresentOrElse(v -> fail(), () -> { throw new ObscureException(); });
+            fail();
+        } catch (ObscureException expected) {
+        } catch (AssertionError e) {
+            throw e;
+        } catch (Throwable t) {
+            fail();
+        }
+
         assertEquals(2.0, empty.orElse(2.0));
         assertEquals(2.0, empty.orElseGet(()-> 2.0));
     }
 
-        @Test(expectedExceptions=NoSuchElementException.class)
-        public void testEmptyGet() {
-            OptionalDouble empty = OptionalDouble.empty();
+    @Test(groups = "unit")
+    public void testIfPresentAndOrElseAndNull() {
+        OptionalDouble empty = OptionalDouble.empty();
+        OptionalDouble present = OptionalDouble.of(1.0);
 
-            double got = empty.getAsDouble();
-        }
+        // No NPE
+        present.ifPresentOrElse(v -> {}, null);
+        empty.ifPresent(null);
+        empty.ifPresentOrElse(null, () -> {});
 
-        @Test(expectedExceptions=NullPointerException.class)
-        public void testEmptyOrElseGetNull() {
-            OptionalDouble empty = OptionalDouble.empty();
-
-            double got = empty.orElseGet(null);
-        }
+        // NPE
+        try {
+            present.ifPresent(null);
+            fail();
+        } catch (NullPointerException ex) {}
+        try {
+            present.ifPresentOrElse(null, () -> {});
+            fail();
+        } catch (NullPointerException ex) {}
+        try {
+            empty.ifPresentOrElse(v -> {}, null);
+            fail();
+        } catch (NullPointerException ex) {}
+    }
 
-        @Test(expectedExceptions=NullPointerException.class)
-        public void testEmptyOrElseThrowNull() throws Throwable {
-            OptionalDouble empty = OptionalDouble.empty();
+    @Test(expectedExceptions=NoSuchElementException.class)
+    public void testEmptyGet() {
+        OptionalDouble empty = OptionalDouble.empty();
+
+        double got = empty.getAsDouble();
+    }
 
-            double got = empty.orElseThrow(null);
-        }
+    @Test(expectedExceptions=NullPointerException.class)
+    public void testEmptyOrElseGetNull() {
+        OptionalDouble empty = OptionalDouble.empty();
+
+        double got = empty.orElseGet(null);
+    }
 
-        @Test(expectedExceptions=ObscureException.class)
-        public void testEmptyOrElseThrow() throws Exception {
-            OptionalDouble empty = OptionalDouble.empty();
+    @Test(expectedExceptions=NullPointerException.class)
+    public void testEmptyOrElseThrowNull() throws Throwable {
+        OptionalDouble empty = OptionalDouble.empty();
+
+        double got = empty.orElseThrow(null);
+    }
 
-            double got = empty.orElseThrow(ObscureException::new);
-        }
+    @Test(expectedExceptions=ObscureException.class)
+    public void testEmptyOrElseThrow() throws Exception {
+        OptionalDouble empty = OptionalDouble.empty();
 
-        @Test(groups = "unit")
-        public void testPresent() {
+        double got = empty.orElseThrow(ObscureException::new);
+    }
+
+    @Test(groups = "unit")
+    public void testPresent() {
         OptionalDouble empty = OptionalDouble.empty();
         OptionalDouble present = OptionalDouble.of(1.0);
 
@@ -96,12 +138,33 @@
         assertFalse(present.toString().isEmpty());
         assertTrue(-1 != present.toString().indexOf(Double.toString(present.getAsDouble()).toString()));
         assertEquals(1.0, present.getAsDouble());
+
+        AtomicBoolean presentCheck = new AtomicBoolean();
+        present.ifPresent(v -> presentCheck.set(true));
+        assertTrue(presentCheck.get());
+        presentCheck.set(false);
+        present.ifPresentOrElse(v -> presentCheck.set(true), () -> fail());
+        assertTrue(presentCheck.get());
+
         try {
             present.ifPresent(v -> { throw new ObscureException(); });
             fail();
-        } catch(ObscureException expected) {
+        } catch (ObscureException expected) {
+        } catch (AssertionError e) {
+            throw e;
+        } catch (Throwable t) {
+            fail();
+        }
+        try {
+            present.ifPresentOrElse(v -> { throw new ObscureException(); }, () -> fail());
+            fail();
+        } catch (ObscureException expected) {
+        } catch (AssertionError e) {
+            throw e;
+        } catch (Throwable t) {
+            fail();
+        }
 
-        }
         assertEquals(1.0, present.orElse(2.0));
         assertEquals(1.0, present.orElseGet(null));
         assertEquals(1.0, present.orElseGet(()-> 2.0));
diff -r e3028445a1ff -r 8498cdb7c54b jdk/test/java/util/Optional/BasicInt.java
--- a/jdk/test/java/util/Optional/BasicInt.java	Fri Feb 13 11:03:57 2015 +0800
+++ b/jdk/test/java/util/Optional/BasicInt.java	Fri Feb 13 11:13:27 2015 +0100
@@ -29,6 +29,7 @@
 
 import java.util.NoSuchElementException;
 import java.util.OptionalInt;
+import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.stream.IntStream;
 
 import static org.testng.Assert.*;
@@ -49,11 +50,52 @@
         assertTrue(0 == empty.hashCode());
         assertTrue(!empty.toString().isEmpty());
         assertTrue(!empty.isPresent());
+
         empty.ifPresent(v -> { fail(); });
+
+        AtomicBoolean emptyCheck = new AtomicBoolean();
+        empty.ifPresentOrElse(v -> fail(), () -> emptyCheck.set(true));
+        assertTrue(emptyCheck.get());
+
+        try {
+            empty.ifPresentOrElse(v -> fail(), () -> { throw new ObscureException(); });
+            fail();
+        } catch (ObscureException expected) {
+        } catch (AssertionError e) {
+            throw e;
+        } catch (Throwable t) {
+            fail();
+        }
+
         assertEquals(2, empty.orElse(2));
         assertEquals(2, empty.orElseGet(()-> 2));
     }
 
+    @Test(groups = "unit")
+    public void testIfPresentAndOrElseAndNull() {
+        OptionalInt empty = OptionalInt.empty();
+        OptionalInt present = OptionalInt.of(1);
+
+        // No NPE
+        present.ifPresentOrElse(v -> {}, null);
+        empty.ifPresent(null);
+        empty.ifPresentOrElse(null, () -> {});
+
+        // NPE
+        try {
+            present.ifPresent(null);
+            fail();
+        } catch (NullPointerException ex) {}
+        try {
+            present.ifPresentOrElse(null, () -> {});
+            fail();
+        } catch (NullPointerException ex) {}
+        try {
+            empty.ifPresentOrElse(v -> {}, null);
+            fail();
+        } catch (NullPointerException ex) {}
+    }
+
     @Test(expectedExceptions=NoSuchElementException.class)
     public void testEmptyGet() {
         OptionalInt empty = OptionalInt.empty();
@@ -96,12 +138,33 @@
         assertFalse(present.toString().isEmpty());
         assertTrue(-1 != present.toString().indexOf(Integer.toString(present.getAsInt()).toString()));
         assertEquals(1, present.getAsInt());
+
+        AtomicBoolean presentCheck = new AtomicBoolean();
+        present.ifPresent(v -> presentCheck.set(true));
+        assertTrue(presentCheck.get());
+        presentCheck.set(false);
+        present.ifPresentOrElse(v -> presentCheck.set(true), () -> fail());
+        assertTrue(presentCheck.get());
+
         try {
             present.ifPresent(v -> { throw new ObscureException(); });
             fail();
-        } catch(ObscureException expected) {
+        } catch (ObscureException expected) {
+        } catch (AssertionError e) {
+            throw e;
+        } catch (Throwable t) {
+            fail();
+        }
+        try {
+            present.ifPresentOrElse(v -> { throw new ObscureException(); }, () -> fail());
+            fail();
+        } catch (ObscureException expected) {
+        } catch (AssertionError e) {
+            throw e;
+        } catch (Throwable t) {
+            fail();
+        }
 
-        }
         assertEquals(1, present.orElse(2));
         assertEquals(1, present.orElseGet(null));
         assertEquals(1, present.orElseGet(()-> 2));
diff -r e3028445a1ff -r 8498cdb7c54b jdk/test/java/util/Optional/BasicLong.java
--- a/jdk/test/java/util/Optional/BasicLong.java	Fri Feb 13 11:03:57 2015 +0800
+++ b/jdk/test/java/util/Optional/BasicLong.java	Fri Feb 13 11:13:27 2015 +0100
@@ -29,6 +29,7 @@
 
 import java.util.NoSuchElementException;
 import java.util.OptionalLong;
+import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.stream.LongStream;
 
 import static org.testng.Assert.*;
@@ -49,41 +50,82 @@
         assertTrue(0 == empty.hashCode());
         assertTrue(!empty.toString().isEmpty());
         assertTrue(!empty.isPresent());
+
         empty.ifPresent(v -> { fail(); });
+
+        AtomicBoolean emptyCheck = new AtomicBoolean();
+        empty.ifPresentOrElse(v -> fail(), () -> emptyCheck.set(true));
+        assertTrue(emptyCheck.get());
+
+        try {
+            empty.ifPresentOrElse(v -> fail(), () -> { throw new ObscureException(); });
+            fail();
+        } catch (ObscureException expected) {
+        } catch (AssertionError e) {
+            throw e;
+        } catch (Throwable t) {
+            fail();
+        }
+
         assertEquals(2, empty.orElse(2));
         assertEquals(2, empty.orElseGet(()-> 2));
     }
 
-        @Test(expectedExceptions=NoSuchElementException.class)
-        public void testEmptyGet() {
-            OptionalLong empty = OptionalLong.empty();
+    @Test(groups = "unit")
+    public void testIfPresentAndOrElseAndNull() {
+        OptionalLong empty = OptionalLong.empty();
+        OptionalLong present = OptionalLong.of(1);
 
-            long got = empty.getAsLong();
-        }
+        // No NPE
+        present.ifPresentOrElse(v -> {}, null);
+        empty.ifPresent(null);
+        empty.ifPresentOrElse(null, () -> {});
 
-        @Test(expectedExceptions=NullPointerException.class)
-        public void testEmptyOrElseGetNull() {
-            OptionalLong empty = OptionalLong.empty();
-
-            long got = empty.orElseGet(null);
-        }
+        // NPE
+        try {
+            present.ifPresent(null);
+            fail();
+        } catch (NullPointerException ex) {}
+        try {
+            present.ifPresentOrElse(null, () -> {});
+            fail();
+        } catch (NullPointerException ex) {}
+        try {
+            empty.ifPresentOrElse(v -> {}, null);
+            fail();
+        } catch (NullPointerException ex) {}
+    }
 
-        @Test(expectedExceptions=NullPointerException.class)
-        public void testEmptyOrElseThrowNull() throws Throwable {
-            OptionalLong empty = OptionalLong.empty();
+    @Test(expectedExceptions=NoSuchElementException.class)
+    public void testEmptyGet() {
+        OptionalLong empty = OptionalLong.empty();
+
+        long got = empty.getAsLong();
+    }
 
-            long got = empty.orElseThrow(null);
-        }
+    @Test(expectedExceptions=NullPointerException.class)
+    public void testEmptyOrElseGetNull() {
+        OptionalLong empty = OptionalLong.empty();
+
+        long got = empty.orElseGet(null);
+    }
 
-        @Test(expectedExceptions=ObscureException.class)
-        public void testEmptyOrElseThrow() throws Exception {
-            OptionalLong empty = OptionalLong.empty();
+    @Test(expectedExceptions=NullPointerException.class)
+    public void testEmptyOrElseThrowNull() throws Throwable {
+        OptionalLong empty = OptionalLong.empty();
+
+        long got = empty.orElseThrow(null);
+    }
 
-            long got = empty.orElseThrow(ObscureException::new);
-        }
+    @Test(expectedExceptions=ObscureException.class)
+    public void testEmptyOrElseThrow() throws Exception {
+        OptionalLong empty = OptionalLong.empty();
 
-        @Test(groups = "unit")
-        public void testPresent() {
+        long got = empty.orElseThrow(ObscureException::new);
+    }
+
+    @Test(groups = "unit")
+    public void testPresent() {
         OptionalLong empty = OptionalLong.empty();
         OptionalLong present = OptionalLong.of(1L);
 
@@ -96,12 +138,35 @@
         assertFalse(present.toString().isEmpty());
         assertTrue(-1 != present.toString().indexOf(Long.toString(present.getAsLong()).toString()));
         assertEquals(1L, present.getAsLong());
+
+        AtomicBoolean presentCheck = new AtomicBoolean();
+        present.ifPresent(v -> presentCheck.set(true));
+        assertTrue(presentCheck.get());
+        presentCheck.set(false);
+        present.ifPresentOrElse(v -> presentCheck.set(true), () -> fail());
+        assertTrue(presentCheck.get());
+
         try {
             present.ifPresent(v -> { throw new ObscureException(); });
             fail();
-        } catch(ObscureException expected) {
+        } catch (ObscureException expected) {
+        } catch (AssertionError e) {
+            throw e;
+        } catch (Throwable t) {
+            fail();
+        }
+        try {
+            present.ifPresentOrElse(v -> {
+                throw new ObscureException();
+            }, () -> fail());
+            fail();
+        } catch (ObscureException expected) {
+        } catch (AssertionError e) {
+            throw e;
+        } catch (Throwable t) {
+            fail();
+        }
 
-        }
         assertEquals(1, present.orElse(2));
         assertEquals(1, present.orElseGet(null));
         assertEquals(1, present.orElseGet(()-> 2));