--- old/src/java.base/share/classes/java/util/Optional.java 2015-02-12 18:48:47.000000000 +0100 +++ new/src/java.base/share/classes/java/util/Optional.java 2015-02-12 18:48:47.000000000 +0100 @@ -38,8 +38,8 @@ *

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). * *

This is a value-based * 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 consumer) { + public void ifPresent(Consumer 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 action, Runnable emptyAction) { + if (value != null) { + action.accept(value); + } else { + emptyAction.run(); } } --- old/src/java.base/share/classes/java/util/OptionalDouble.java 2015-02-12 18:48:48.000000000 +0100 +++ new/src/java.base/share/classes/java/util/OptionalDouble.java 2015-02-12 18:48:48.000000000 +0100 @@ -37,8 +37,8 @@ *

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). * *

This is a value-based * 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(); } } --- old/src/java.base/share/classes/java/util/OptionalInt.java 2015-02-12 18:48:50.000000000 +0100 +++ new/src/java.base/share/classes/java/util/OptionalInt.java 2015-02-12 18:48:49.000000000 +0100 @@ -37,8 +37,8 @@ *

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). * *

This is a value-based * 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(); } } --- old/src/java.base/share/classes/java/util/OptionalLong.java 2015-02-12 18:48:51.000000000 +0100 +++ new/src/java.base/share/classes/java/util/OptionalLong.java 2015-02-12 18:48:51.000000000 +0100 @@ -37,8 +37,8 @@ *

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). * *

This is a value-based * 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(); } } --- old/test/java/util/Optional/Basic.java 2015-02-12 18:48:52.000000000 +0100 +++ new/test/java/util/Optional/Basic.java 2015-02-12 18:48:52.000000000 +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 empty = Optional.empty(); + Optional 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 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)); --- old/test/java/util/Optional/BasicDouble.java 2015-02-12 18:48:53.000000000 +0100 +++ new/test/java/util/Optional/BasicDouble.java 2015-02-12 18:48:53.000000000 +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(); + // 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) {} + } - double got = empty.orElseGet(null); - } + @Test(expectedExceptions=NoSuchElementException.class) + public void testEmptyGet() { + OptionalDouble empty = OptionalDouble.empty(); - @Test(expectedExceptions=NullPointerException.class) - public void testEmptyOrElseThrowNull() throws Throwable { - OptionalDouble empty = OptionalDouble.empty(); + double got = empty.getAsDouble(); + } - double got = empty.orElseThrow(null); - } + @Test(expectedExceptions=NullPointerException.class) + public void testEmptyOrElseGetNull() { + OptionalDouble empty = OptionalDouble.empty(); - @Test(expectedExceptions=ObscureException.class) - public void testEmptyOrElseThrow() throws Exception { - OptionalDouble empty = OptionalDouble.empty(); + double got = empty.orElseGet(null); + } - double got = empty.orElseThrow(ObscureException::new); - } + @Test(expectedExceptions=NullPointerException.class) + public void testEmptyOrElseThrowNull() throws Throwable { + OptionalDouble empty = OptionalDouble.empty(); - @Test(groups = "unit") - public void testPresent() { + double got = empty.orElseThrow(null); + } + + @Test(expectedExceptions=ObscureException.class) + public void testEmptyOrElseThrow() throws Exception { + OptionalDouble empty = OptionalDouble.empty(); + + 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)); --- old/test/java/util/Optional/BasicInt.java 2015-02-12 18:48:54.000000000 +0100 +++ new/test/java/util/Optional/BasicInt.java 2015-02-12 18:48:54.000000000 +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)); --- old/test/java/util/Optional/BasicLong.java 2015-02-12 18:48:55.000000000 +0100 +++ new/test/java/util/Optional/BasicLong.java 2015-02-12 18:48:55.000000000 +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(); + // 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) {} + } - long got = empty.orElseGet(null); - } + @Test(expectedExceptions=NoSuchElementException.class) + public void testEmptyGet() { + OptionalLong empty = OptionalLong.empty(); - @Test(expectedExceptions=NullPointerException.class) - public void testEmptyOrElseThrowNull() throws Throwable { - OptionalLong empty = OptionalLong.empty(); + long got = empty.getAsLong(); + } - long got = empty.orElseThrow(null); - } + @Test(expectedExceptions=NullPointerException.class) + public void testEmptyOrElseGetNull() { + OptionalLong empty = OptionalLong.empty(); - @Test(expectedExceptions=ObscureException.class) - public void testEmptyOrElseThrow() throws Exception { - OptionalLong empty = OptionalLong.empty(); + long got = empty.orElseGet(null); + } - long got = empty.orElseThrow(ObscureException::new); - } + @Test(expectedExceptions=NullPointerException.class) + public void testEmptyOrElseThrowNull() throws Throwable { + OptionalLong empty = OptionalLong.empty(); - @Test(groups = "unit") - public void testPresent() { + long got = empty.orElseThrow(null); + } + + @Test(expectedExceptions=ObscureException.class) + public void testEmptyOrElseThrow() throws Exception { + OptionalLong empty = OptionalLong.empty(); + + 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));