diff --git a/core-java-modules/core-java-lambdas/README.md b/core-java-modules/core-java-lambdas/README.md
new file mode 100644
index 0000000000..cad2097673
--- /dev/null
+++ b/core-java-modules/core-java-lambdas/README.md
@@ -0,0 +1,12 @@
+## Relevant articles:
+
+- [Why Do Local Variables Used in Lambdas Have to Be Final or Effectively Final?](https://www.baeldung.com/java-lambda-effectively-final-local-variables)
+- [Java 8 – Powerful Comparison with Lambdas](http://www.baeldung.com/java-8-sort-lambda)
+- [Functional Interfaces in Java 8](http://www.baeldung.com/java-8-functional-interfaces)
+- [Lambda Expressions and Functional Interfaces: Tips and Best Practices](http://www.baeldung.com/java-8-lambda-expressions-tips)
+- [Exceptions in Java 8 Lambda Expressions](http://www.baeldung.com/java-lambda-exceptions)
+- [Method References in Java](https://www.baeldung.com/java-method-references)
+- [The Double Colon Operator in Java 8](https://www.baeldung.com/java-8-double-colon-operator)
+- [Serialize a Lambda in Java](https://www.baeldung.com/java-serialize-lambda)
+- [Convert Anonymous Class into Lambda in Java](https://www.baeldung.com/java-from-anonymous-class-to-lambda)
+- [When to Use Callable and Supplier in Java](https://www.baeldung.com/java-callable-vs-supplier)
diff --git a/core-java-modules/core-java-lambdas/pom.xml b/core-java-modules/core-java-lambdas/pom.xml
new file mode 100644
index 0000000000..0e6b049d2a
--- /dev/null
+++ b/core-java-modules/core-java-lambdas/pom.xml
@@ -0,0 +1,25 @@
+
+
+ 4.0.0
+ core-java-lambdas
+ jar
+ core-java-lambdas
+
+
+ com.ossez.core-java-modules
+ core-java-modules
+ 0.0.2-SNAPSHOT
+ ../pom.xml
+
+
+
+
+ org.apache.commons
+ commons-lang3
+ ${commons-lang3.version}
+
+
+
+
\ No newline at end of file
diff --git a/core-java-modules/core-java-lambdas/src/main/java/com/baeldung/doublecolon/Computer.java b/core-java-modules/core-java-lambdas/src/main/java/com/baeldung/doublecolon/Computer.java
new file mode 100644
index 0000000000..dc0b064013
--- /dev/null
+++ b/core-java-modules/core-java-lambdas/src/main/java/com/baeldung/doublecolon/Computer.java
@@ -0,0 +1,85 @@
+package com.baeldung.doublecolon;
+
+public class Computer {
+
+ private Integer age;
+ private String color;
+ private Integer healty;
+
+ Computer(final int age, final String color) {
+ this.age = age;
+ this.color = color;
+ }
+
+ Computer(final Integer age, final String color, final Integer healty) {
+ this.age = age;
+ this.color = color;
+ this.healty = healty;
+ }
+
+ public Computer() {
+ }
+
+ public Integer getAge() {
+ return age;
+ }
+
+ public void setAge(final Integer age) {
+ this.age = age;
+ }
+
+ String getColor() {
+ return color;
+ }
+
+ public void setColor(final String color) {
+ this.color = color;
+ }
+
+ Integer getHealty() {
+ return healty;
+ }
+
+ void setHealty(final Integer healty) {
+ this.healty = healty;
+ }
+
+ public void turnOnPc() {
+ System.out.println("Computer turned on");
+ }
+
+ public void turnOffPc() {
+ System.out.println("Computer turned off");
+ }
+
+ public Double calculateValue(Double initialValue) {
+ return initialValue / 1.50;
+ }
+
+ @Override
+ public String toString() {
+ return "Computer{" + "age=" + age + ", color='" + color + '\'' + ", healty=" + healty + '}';
+ }
+
+ @Override
+ public boolean equals(final Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+
+ final Computer computer = (Computer) o;
+
+ return (age != null ? age.equals(computer.age) : computer.age == null) && (color != null ? color.equals(computer.color) : computer.color == null);
+
+ }
+
+ @Override
+ public int hashCode() {
+ int result = age != null ? age.hashCode() : 0;
+ result = 31 * result + (color != null ? color.hashCode() : 0);
+ return result;
+ }
+}
diff --git a/core-java-modules/core-java-lambdas/src/main/java/com/baeldung/doublecolon/ComputerUtils.java b/core-java-modules/core-java-lambdas/src/main/java/com/baeldung/doublecolon/ComputerUtils.java
new file mode 100644
index 0000000000..ea274072ea
--- /dev/null
+++ b/core-java-modules/core-java-lambdas/src/main/java/com/baeldung/doublecolon/ComputerUtils.java
@@ -0,0 +1,27 @@
+package com.baeldung.doublecolon;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import com.baeldung.doublecolon.function.ComputerPredicate;
+
+public class ComputerUtils {
+
+ static final ComputerPredicate after2010Predicate = (c) -> (c.getAge() > 2010);
+ static final ComputerPredicate blackPredicate = (c) -> "black".equals(c.getColor());
+
+ public static List filter(final List inventory, final ComputerPredicate p) {
+
+ final List result = new ArrayList<>();
+ inventory.stream().filter(p::filter).forEach(result::add);
+
+ return result;
+ }
+
+ static void repair(final Computer computer) {
+ if (computer.getHealty() < 50) {
+ computer.setHealty(100);
+ }
+ }
+
+}
diff --git a/core-java-modules/core-java-lambdas/src/main/java/com/baeldung/doublecolon/MacbookPro.java b/core-java-modules/core-java-lambdas/src/main/java/com/baeldung/doublecolon/MacbookPro.java
new file mode 100644
index 0000000000..79c8d9e383
--- /dev/null
+++ b/core-java-modules/core-java-lambdas/src/main/java/com/baeldung/doublecolon/MacbookPro.java
@@ -0,0 +1,39 @@
+package com.baeldung.doublecolon;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.function.Function;
+
+public class MacbookPro extends Computer {
+
+ private static final Logger LOG = LoggerFactory.getLogger(MacbookPro.class);
+
+ public MacbookPro(int age, String color) {
+ super(age, color);
+ }
+
+ MacbookPro(Integer age, String color, Integer healty) {
+ super(age, color, healty);
+ }
+
+ @Override
+ public void turnOnPc() {
+ LOG.debug("MacbookPro turned on");
+ }
+
+ @Override
+ public void turnOffPc() {
+ LOG.debug("MacbookPro turned off");
+ }
+
+ @Override
+ public Double calculateValue(Double initialValue) {
+
+ Function function = super::calculateValue;
+ final Double pcValue = function.apply(initialValue);
+ LOG.debug("First value is:" + pcValue);
+ return pcValue + (initialValue / 10);
+
+ }
+}
diff --git a/core-java-modules/core-java-lambdas/src/main/java/com/baeldung/doublecolon/function/ComputerPredicate.java b/core-java-modules/core-java-lambdas/src/main/java/com/baeldung/doublecolon/function/ComputerPredicate.java
new file mode 100644
index 0000000000..5ce491e86a
--- /dev/null
+++ b/core-java-modules/core-java-lambdas/src/main/java/com/baeldung/doublecolon/function/ComputerPredicate.java
@@ -0,0 +1,10 @@
+package com.baeldung.doublecolon.function;
+
+import com.baeldung.doublecolon.Computer;
+
+@FunctionalInterface
+public interface ComputerPredicate {
+
+ boolean filter(Computer c);
+
+}
diff --git a/core-java-modules/core-java-lambdas/src/main/java/com/baeldung/doublecolon/function/TriFunction.java b/core-java-modules/core-java-lambdas/src/main/java/com/baeldung/doublecolon/function/TriFunction.java
new file mode 100644
index 0000000000..d0d6299479
--- /dev/null
+++ b/core-java-modules/core-java-lambdas/src/main/java/com/baeldung/doublecolon/function/TriFunction.java
@@ -0,0 +1,15 @@
+package com.baeldung.doublecolon.function;
+
+import java.util.Objects;
+import java.util.function.Function;
+
+@FunctionalInterface
+public interface TriFunction {
+
+ R apply(A a, B b, C c);
+
+ default TriFunction andThen(final Function super R, ? extends V> after) {
+ Objects.requireNonNull(after);
+ return (final A a, final B b, final C c) -> after.apply(apply(a, b, c));
+ }
+}
\ No newline at end of file
diff --git a/core-java-modules/core-java-lambdas/src/main/java/com/baeldung/java8/entity/Human.java b/core-java-modules/core-java-lambdas/src/main/java/com/baeldung/java8/entity/Human.java
new file mode 100644
index 0000000000..98e35d0af2
--- /dev/null
+++ b/core-java-modules/core-java-lambdas/src/main/java/com/baeldung/java8/entity/Human.java
@@ -0,0 +1,89 @@
+package com.baeldung.java8.entity;
+
+public class Human {
+ private String name;
+ private int age;
+
+ public Human() {
+ super();
+ }
+
+ public Human(final String name, final int age) {
+ super();
+
+ this.name = name;
+ this.age = age;
+ }
+
+ // API
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(final String name) {
+ this.name = name;
+ }
+
+ public int getAge() {
+ return age;
+ }
+
+ public void setAge(final int age) {
+ this.age = age;
+ }
+
+ // compare
+
+ public static int compareByNameThenAge(final Human lhs, final Human rhs) {
+ if (lhs.name.equals(rhs.name)) {
+ return Integer.compare(lhs.age, rhs.age);
+ } else {
+ return lhs.name.compareTo(rhs.name);
+ }
+ }
+
+ //
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + age;
+ result = prime * result + ((name == null) ? 0 : name.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(final Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ final Human other = (Human) obj;
+ if (age != other.age) {
+ return false;
+ }
+ if (name == null) {
+ if (other.name != null) {
+ return false;
+ }
+ } else if (!name.equals(other.name)) {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder builder = new StringBuilder();
+ builder.append("Human [name=").append(name).append(", age=").append(age).append("]");
+ return builder.toString();
+ }
+
+}
diff --git a/core-java-modules/core-java-lambdas/src/main/java/com/baeldung/java8/lambda/exceptions/LambdaExceptionWrappers.java b/core-java-modules/core-java-lambdas/src/main/java/com/baeldung/java8/lambda/exceptions/LambdaExceptionWrappers.java
new file mode 100644
index 0000000000..db710589e7
--- /dev/null
+++ b/core-java-modules/core-java-lambdas/src/main/java/com/baeldung/java8/lambda/exceptions/LambdaExceptionWrappers.java
@@ -0,0 +1,62 @@
+package com.baeldung.java8.lambda.exceptions;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.function.Consumer;
+
+public class LambdaExceptionWrappers {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(LambdaExceptionWrappers.class);
+
+ public static Consumer lambdaWrapper(Consumer consumer) {
+ return i -> {
+ try {
+ consumer.accept(i);
+ } catch (ArithmeticException e) {
+ LOGGER.error("Arithmetic Exception occurred.", e);
+ }
+ };
+ }
+
+ static Consumer consumerWrapper(Consumer consumer, Class clazz) {
+ return i -> {
+ try {
+ consumer.accept(i);
+ } catch (Exception ex) {
+ try {
+ E exCast = clazz.cast(ex);
+ LOGGER.error("Exception occurred.", exCast);
+ } catch (ClassCastException ccEx) {
+ throw ex;
+ }
+ }
+ };
+ }
+
+ public static Consumer throwingConsumerWrapper(ThrowingConsumer throwingConsumer) {
+ return i -> {
+ try {
+ throwingConsumer.accept(i);
+ } catch (Exception ex) {
+ throw new RuntimeException(ex);
+ }
+ };
+ }
+
+ public static Consumer handlingConsumerWrapper(ThrowingConsumer throwingConsumer, Class exceptionClass) {
+ return i -> {
+ try {
+ throwingConsumer.accept(i);
+ } catch (Exception ex) {
+ try {
+ E exCast = exceptionClass.cast(ex);
+ LOGGER.error("Exception occurred.", exCast);
+ } catch (ClassCastException ccEx) {
+ throw new RuntimeException(ex);
+ }
+ }
+ };
+ }
+
+}
\ No newline at end of file
diff --git a/core-java-modules/core-java-lambdas/src/main/java/com/baeldung/java8/lambda/exceptions/ThrowingConsumer.java b/core-java-modules/core-java-lambdas/src/main/java/com/baeldung/java8/lambda/exceptions/ThrowingConsumer.java
new file mode 100644
index 0000000000..c5860e7f6b
--- /dev/null
+++ b/core-java-modules/core-java-lambdas/src/main/java/com/baeldung/java8/lambda/exceptions/ThrowingConsumer.java
@@ -0,0 +1,8 @@
+package com.baeldung.java8.lambda.exceptions;
+
+@FunctionalInterface
+public interface ThrowingConsumer {
+
+ void accept(T t) throws E;
+
+}
\ No newline at end of file
diff --git a/core-java-modules/core-java-lambdas/src/main/java/com/baeldung/java8/lambda/tips/Bar.java b/core-java-modules/core-java-lambdas/src/main/java/com/baeldung/java8/lambda/tips/Bar.java
new file mode 100644
index 0000000000..3ee78bd7a3
--- /dev/null
+++ b/core-java-modules/core-java-lambdas/src/main/java/com/baeldung/java8/lambda/tips/Bar.java
@@ -0,0 +1,16 @@
+package com.baeldung.java8.lambda.tips;
+
+
+@FunctionalInterface
+public interface Bar {
+
+ String method(String string);
+
+ default String defaultBar() {
+ return "Default String from Bar";
+ }
+
+ default String defaultCommon() {
+ return "Default Common from Bar";
+ }
+}
diff --git a/core-java-modules/core-java-lambdas/src/main/java/com/baeldung/java8/lambda/tips/Baz.java b/core-java-modules/core-java-lambdas/src/main/java/com/baeldung/java8/lambda/tips/Baz.java
new file mode 100644
index 0000000000..1e1e9ae094
--- /dev/null
+++ b/core-java-modules/core-java-lambdas/src/main/java/com/baeldung/java8/lambda/tips/Baz.java
@@ -0,0 +1,16 @@
+package com.baeldung.java8.lambda.tips;
+
+
+@FunctionalInterface
+public interface Baz {
+
+ String method(String string);
+
+ default String defaultBaz() {
+ return "Default String from Baz";
+ }
+
+ default String defaultCommon(){
+ return "Default Common from Baz";
+ }
+}
diff --git a/core-java-modules/core-java-lambdas/src/main/java/com/baeldung/java8/lambda/tips/Foo.java b/core-java-modules/core-java-lambdas/src/main/java/com/baeldung/java8/lambda/tips/Foo.java
new file mode 100644
index 0000000000..b63ba61e7e
--- /dev/null
+++ b/core-java-modules/core-java-lambdas/src/main/java/com/baeldung/java8/lambda/tips/Foo.java
@@ -0,0 +1,11 @@
+package com.baeldung.java8.lambda.tips;
+
+
+@FunctionalInterface
+public interface Foo {
+
+ String method(String string);
+
+ default void defaultMethod() {
+ }
+}
diff --git a/core-java-modules/core-java-lambdas/src/main/java/com/baeldung/java8/lambda/tips/FooExtended.java b/core-java-modules/core-java-lambdas/src/main/java/com/baeldung/java8/lambda/tips/FooExtended.java
new file mode 100644
index 0000000000..27ab86dca3
--- /dev/null
+++ b/core-java-modules/core-java-lambdas/src/main/java/com/baeldung/java8/lambda/tips/FooExtended.java
@@ -0,0 +1,11 @@
+package com.baeldung.java8.lambda.tips;
+
+
+@FunctionalInterface
+public interface FooExtended extends Baz, Bar {
+
+ @Override
+ default String defaultCommon() {
+ return Bar.super.defaultCommon();
+ }
+}
diff --git a/core-java-modules/core-java-lambdas/src/main/java/com/baeldung/java8/lambda/tips/Processor.java b/core-java-modules/core-java-lambdas/src/main/java/com/baeldung/java8/lambda/tips/Processor.java
new file mode 100644
index 0000000000..7931129cf5
--- /dev/null
+++ b/core-java-modules/core-java-lambdas/src/main/java/com/baeldung/java8/lambda/tips/Processor.java
@@ -0,0 +1,12 @@
+package com.baeldung.java8.lambda.tips;
+
+import java.util.concurrent.Callable;
+import java.util.function.Supplier;
+
+public interface Processor {
+
+ String processWithCallable(Callable c) throws Exception;
+
+ String processWithSupplier(Supplier s);
+
+}
diff --git a/core-java-modules/core-java-lambdas/src/main/java/com/baeldung/java8/lambda/tips/ProcessorImpl.java b/core-java-modules/core-java-lambdas/src/main/java/com/baeldung/java8/lambda/tips/ProcessorImpl.java
new file mode 100644
index 0000000000..cb1b3dcdd2
--- /dev/null
+++ b/core-java-modules/core-java-lambdas/src/main/java/com/baeldung/java8/lambda/tips/ProcessorImpl.java
@@ -0,0 +1,20 @@
+package com.baeldung.java8.lambda.tips;
+
+
+import java.util.concurrent.Callable;
+import java.util.function.Consumer;
+import java.util.function.Function;
+import java.util.function.Supplier;
+
+public class ProcessorImpl implements Processor {
+
+ @Override
+ public String processWithCallable(Callable c) throws Exception {
+ return c.call();
+ }
+
+ @Override
+ public String processWithSupplier(Supplier s) {
+ return s.get();
+ }
+}
diff --git a/core-java-modules/core-java-lambdas/src/main/java/com/baeldung/java8/lambda/tips/UseFoo.java b/core-java-modules/core-java-lambdas/src/main/java/com/baeldung/java8/lambda/tips/UseFoo.java
new file mode 100644
index 0000000000..a64d8bb920
--- /dev/null
+++ b/core-java-modules/core-java-lambdas/src/main/java/com/baeldung/java8/lambda/tips/UseFoo.java
@@ -0,0 +1,38 @@
+package com.baeldung.java8.lambda.tips;
+
+
+import java.util.function.Function;
+
+public class UseFoo {
+
+ private String value = "Enclosing scope value";
+
+ public String add(final String string, final Foo foo) {
+ return foo.method(string);
+ }
+
+ public String addWithStandardFI(final String string, final Function fn) {
+ return fn.apply(string);
+ }
+
+ public String scopeExperiment() {
+ final Foo fooIC = new Foo() {
+ String value = "Inner class value";
+
+ @Override
+ public String method(final String string) {
+ return value;
+ }
+ };
+ final String resultIC = fooIC.method("");
+
+ final Foo fooLambda = parameter -> {
+ final String value = "Lambda value";
+ return this.value;
+ };
+ final String resultLambda = fooLambda.method("");
+
+ return "Results: resultIC = " + resultIC + ", resultLambda = " + resultLambda;
+ }
+
+}
diff --git a/core-java-modules/core-java-lambdas/src/main/java/com/baeldung/lambdas/LambdaVariables.java b/core-java-modules/core-java-lambdas/src/main/java/com/baeldung/lambdas/LambdaVariables.java
new file mode 100644
index 0000000000..5c1201150f
--- /dev/null
+++ b/core-java-modules/core-java-lambdas/src/main/java/com/baeldung/lambdas/LambdaVariables.java
@@ -0,0 +1,88 @@
+package com.baeldung.lambdas;
+
+import java.util.Random;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.function.Supplier;
+import java.util.stream.IntStream;
+
+/**
+ * Class with examples about working with capturing lambdas.
+ */
+public class LambdaVariables {
+
+ private volatile boolean run = true;
+ private int start = 0;
+
+ private ExecutorService executor = Executors.newFixedThreadPool(3);
+
+ public static void main(String[] args) {
+ new LambdaVariables().localVariableMultithreading();
+ }
+
+ Supplier incrementer(int start) {
+ return () -> start; // can't modify start parameter inside the lambda
+ }
+
+ Supplier incrementer() {
+ return () -> start++;
+ }
+
+ public void localVariableMultithreading() {
+ boolean run = true;
+ executor.execute(() -> {
+ while (run) {
+ // do operation
+ }
+ });
+ // commented because it doesn't compile, it's just an example of non-final local variables in lambdas
+ // run = false;
+ }
+
+ public void instanceVariableMultithreading() {
+ executor.execute(() -> {
+ while (run) {
+ // do operation
+ }
+ });
+
+ run = false;
+ }
+
+ /**
+ * WARNING: always avoid this workaround!!
+ */
+ public void workaroundSingleThread() {
+ int[] holder = new int[] { 2 };
+ IntStream sums = IntStream
+ .of(1, 2, 3)
+ .map(val -> val + holder[0]);
+
+ holder[0] = 0;
+
+ System.out.println(sums.sum());
+ }
+
+ /**
+ * WARNING: always avoid this workaround!!
+ */
+ public void workaroundMultithreading() {
+ int[] holder = new int[] { 2 };
+ Runnable runnable = () -> System.out.println(IntStream
+ .of(1, 2, 3)
+ .map(val -> val + holder[0])
+ .sum());
+
+ new Thread(runnable).start();
+
+ // simulating some processing
+ try {
+ Thread.sleep(new Random().nextInt(3) * 1000L);
+ } catch (InterruptedException e) {
+ throw new RuntimeException(e);
+ }
+
+ holder[0] = 0;
+ }
+
+}
diff --git a/core-java-modules/core-java-lambdas/src/main/resources/logback.xml b/core-java-modules/core-java-lambdas/src/main/resources/logback.xml
new file mode 100644
index 0000000000..7d900d8ea8
--- /dev/null
+++ b/core-java-modules/core-java-lambdas/src/main/resources/logback.xml
@@ -0,0 +1,13 @@
+
+
+
+
+ %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/core-java-modules/core-java-lambdas/src/test/java/com/baeldung/doublecolon/ComputerUtilsUnitTest.java b/core-java-modules/core-java-lambdas/src/test/java/com/baeldung/doublecolon/ComputerUtilsUnitTest.java
new file mode 100644
index 0000000000..7157dead6e
--- /dev/null
+++ b/core-java-modules/core-java-lambdas/src/test/java/com/baeldung/doublecolon/ComputerUtilsUnitTest.java
@@ -0,0 +1,91 @@
+package com.baeldung.doublecolon;
+
+import com.baeldung.doublecolon.function.TriFunction;
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.List;
+import java.util.function.BiFunction;
+
+import static com.baeldung.doublecolon.ComputerUtils.*;
+
+public class ComputerUtilsUnitTest {
+
+ @Before
+ public void setup() {
+ }
+
+ @After
+ public void tearDown() {
+ }
+
+ @Test
+ public void testConstructorReference() {
+
+ Computer c1 = new Computer(2015, "white");
+ Computer c2 = new Computer(2009, "black");
+ Computer c3 = new Computer(2014, "black");
+
+ BiFunction c4Function = Computer::new;
+ Computer c4 = c4Function.apply(2013, "white");
+ BiFunction c5Function = Computer::new;
+ Computer c5 = c5Function.apply(2010, "black");
+ BiFunction c6Function = Computer::new;
+ Computer c6 = c6Function.apply(2008, "black");
+
+ List inventory = Arrays.asList(c1, c2, c3, c4, c5, c6);
+
+ List blackComputer = filter(inventory, blackPredicate);
+ Assert.assertEquals("The black Computers are: ", blackComputer.size(), 4);
+
+ List after2010Computer = filter(inventory, after2010Predicate);
+ Assert.assertEquals("The Computer bought after 2010 are: ", after2010Computer.size(), 3);
+
+ List before2011Computer = filter(inventory, c -> c.getAge() < 2011);
+ Assert.assertEquals("The Computer bought before 2011 are: ", before2011Computer.size(), 3);
+
+ inventory.sort(Comparator.comparing(Computer::getAge));
+
+ Assert.assertEquals("Oldest Computer in inventory", c6, inventory.get(0));
+
+ }
+
+ @Test
+ public void testStaticMethodReference() {
+
+ Computer c1 = new Computer(2015, "white", 35);
+ Computer c2 = new Computer(2009, "black", 65);
+ TriFunction c6Function = Computer::new;
+ Computer c3 = c6Function.apply(2008, "black", 90);
+
+ List inventory = Arrays.asList(c1, c2, c3);
+ inventory.forEach(ComputerUtils::repair);
+
+ Assert.assertEquals("Computer repaired", new Integer(100), c1.getHealty());
+ }
+
+ @Test
+ public void testInstanceMethodArbitraryObjectParticularType() {
+
+ Computer c1 = new Computer(2015, "white", 35);
+ Computer c2 = new MacbookPro(2009, "black", 65);
+ List inventory = Arrays.asList(c1, c2);
+ inventory.forEach(Computer::turnOnPc);
+
+ }
+
+ @Test
+ public void testSuperMethodReference() {
+
+ final TriFunction integerStringIntegerObjectTriFunction = MacbookPro::new;
+ final MacbookPro macbookPro = integerStringIntegerObjectTriFunction.apply(2010, "black", 100);
+ Double initialValue = 999.99;
+ final Double actualValue = macbookPro.calculateValue(initialValue);
+ Assert.assertEquals(766.659, actualValue, 0.0);
+ }
+
+}
diff --git a/core-java-modules/core-java-lambdas/src/test/java/com/baeldung/functionalinterface/FunctionalInterfaceUnitTest.java b/core-java-modules/core-java-lambdas/src/test/java/com/baeldung/functionalinterface/FunctionalInterfaceUnitTest.java
new file mode 100644
index 0000000000..e91cbfcb75
--- /dev/null
+++ b/core-java-modules/core-java-lambdas/src/test/java/com/baeldung/functionalinterface/FunctionalInterfaceUnitTest.java
@@ -0,0 +1,187 @@
+package com.baeldung.functionalinterface;
+
+import com.google.common.util.concurrent.Uninterruptibles;
+import org.junit.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
+import java.util.function.Function;
+import java.util.function.Supplier;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import static org.junit.Assert.*;
+
+public class FunctionalInterfaceUnitTest {
+
+ private static final Logger LOG = LoggerFactory.getLogger(FunctionalInterfaceUnitTest.class);
+
+ @Test
+ public void whenPassingLambdaToComputeIfAbsent_thenTheValueGetsComputedAndPutIntoMap() {
+ Map nameMap = new HashMap<>();
+ Integer value = nameMap.computeIfAbsent("John", String::length);
+
+ assertEquals(new Integer(4), nameMap.get("John"));
+ assertEquals(new Integer(4), value);
+ }
+
+ @Test
+ public void whenPassingMethodReferenceToComputeIfAbsent_thenTheValueGetsComputedAndPutIntoMap() {
+ Map nameMap = new HashMap<>();
+ Integer value = nameMap.computeIfAbsent("John", String::length);
+
+ assertEquals(new Integer(4), nameMap.get("John"));
+ assertEquals(new Integer(4), value);
+ }
+
+ @Test
+ public void whenUsingCustomFunctionalInterfaceForPrimitives_thenCanUseItAsLambda() {
+
+ short[] array = { (short) 1, (short) 2, (short) 3 };
+ byte[] transformedArray = transformArray(array, s -> (byte) (s * 2));
+
+ byte[] expectedArray = { (byte) 2, (byte) 4, (byte) 6 };
+ assertArrayEquals(expectedArray, transformedArray);
+
+ }
+
+ @Test
+ public void whenUsingBiFunction_thenCanUseItToReplaceMapValues() {
+ Map salaries = new HashMap<>();
+ salaries.put("John", 40000);
+ salaries.put("Freddy", 30000);
+ salaries.put("Samuel", 50000);
+
+ salaries.replaceAll((name, oldValue) -> name.equals("Freddy") ? oldValue : oldValue + 10000);
+
+ assertEquals(new Integer(50000), salaries.get("John"));
+ assertEquals(new Integer(30000), salaries.get("Freddy"));
+ assertEquals(new Integer(60000), salaries.get("Samuel"));
+ }
+
+ @Test
+ public void whenPassingLambdaToThreadConstructor_thenLambdaInferredToRunnable() {
+ Thread thread = new Thread(() -> LOG.debug("Hello From Another Thread"));
+ thread.start();
+ }
+
+ @Test
+ public void whenUsingSupplierToGenerateNumbers_thenCanUseItInStreamGenerate() {
+
+ int[] fibs = { 0, 1 };
+ Stream fibonacci = Stream.generate(() -> {
+ int result = fibs[1];
+ int fib3 = fibs[0] + fibs[1];
+ fibs[0] = fibs[1];
+ fibs[1] = fib3;
+ return result;
+ });
+
+ List fibonacci5 = fibonacci.limit(5)
+ .collect(Collectors.toList());
+
+ assertEquals(new Integer(1), fibonacci5.get(0));
+ assertEquals(new Integer(1), fibonacci5.get(1));
+ assertEquals(new Integer(2), fibonacci5.get(2));
+ assertEquals(new Integer(3), fibonacci5.get(3));
+ assertEquals(new Integer(5), fibonacci5.get(4));
+ }
+
+ @Test
+ public void whenUsingConsumerInForEach_thenConsumerExecutesForEachListElement() {
+ List names = Arrays.asList("John", "Freddy", "Samuel");
+ names.forEach(name -> LOG.debug("Hello, " + name));
+ }
+
+ @Test
+ public void whenUsingBiConsumerInForEach_thenConsumerExecutesForEachMapElement() {
+ Map ages = new HashMap<>();
+ ages.put("John", 25);
+ ages.put("Freddy", 24);
+ ages.put("Samuel", 30);
+
+ ages.forEach((name, age) -> LOG.debug(name + " is " + age + " years old"));
+ }
+
+ @Test
+ public void whenUsingPredicateInFilter_thenListValuesAreFilteredOut() {
+ List names = Arrays.asList("Angela", "Aaron", "Bob", "Claire", "David");
+
+ List namesWithA = names.stream()
+ .filter(name -> name.startsWith("A"))
+ .collect(Collectors.toList());
+
+ assertEquals(2, namesWithA.size());
+ assertTrue(namesWithA.contains("Angela"));
+ assertTrue(namesWithA.contains("Aaron"));
+ }
+
+ @Test
+ public void whenUsingUnaryOperatorWithReplaceAll_thenAllValuesInTheListAreReplaced() {
+ List names = Arrays.asList("bob", "josh", "megan");
+
+ names.replaceAll(String::toUpperCase);
+
+ assertEquals("BOB", names.get(0));
+ assertEquals("JOSH", names.get(1));
+ assertEquals("MEGAN", names.get(2));
+ }
+
+ @Test
+ public void whenUsingBinaryOperatorWithStreamReduce_thenResultIsSumOfValues() {
+
+ List values = Arrays.asList(3, 5, 8, 9, 12);
+
+ int sum = values.stream()
+ .reduce(0, (i1, i2) -> i1 + i2);
+
+ assertEquals(37, sum);
+
+ }
+
+ @Test
+ public void whenComposingTwoFunctions_thenFunctionsExecuteSequentially() {
+
+ Function intToString = Object::toString;
+ Function quote = s -> "'" + s + "'";
+
+ Function quoteIntToString = quote.compose(intToString);
+
+ assertEquals("'5'", quoteIntToString.apply(5));
+
+ }
+
+ @Test
+ public void whenUsingSupplierToGenerateValue_thenValueIsGeneratedLazily() {
+
+ Supplier lazyValue = () -> {
+ Uninterruptibles.sleepUninterruptibly(1000, TimeUnit.MILLISECONDS);
+ return 9d;
+ };
+
+ double valueSquared = squareLazy(lazyValue);
+
+ assertEquals(81d, valueSquared, 0);
+
+ }
+
+ //
+
+ public double squareLazy(Supplier lazyValue) {
+ return Math.pow(lazyValue.get(), 2);
+ }
+
+ public byte[] transformArray(short[] array, ShortToByteFunction function) {
+ byte[] transformedArray = new byte[array.length];
+ for (int i = 0; i < array.length; i++) {
+ transformedArray[i] = function.applyAsByte(array[i]);
+ }
+ return transformedArray;
+ }
+
+}
diff --git a/core-java-modules/core-java-lambdas/src/test/java/com/baeldung/functionalinterface/ShortToByteFunction.java b/core-java-modules/core-java-lambdas/src/test/java/com/baeldung/functionalinterface/ShortToByteFunction.java
new file mode 100644
index 0000000000..3231d6244f
--- /dev/null
+++ b/core-java-modules/core-java-lambdas/src/test/java/com/baeldung/functionalinterface/ShortToByteFunction.java
@@ -0,0 +1,8 @@
+package com.baeldung.functionalinterface;
+
+@FunctionalInterface
+public interface ShortToByteFunction {
+
+ byte applyAsByte(short s);
+
+}
diff --git a/core-java-modules/core-java-lambdas/src/test/java/com/baeldung/java8/Java8SortUnitTest.java b/core-java-modules/core-java-lambdas/src/test/java/com/baeldung/java8/Java8SortUnitTest.java
new file mode 100644
index 0000000000..e5f876c84b
--- /dev/null
+++ b/core-java-modules/core-java-lambdas/src/test/java/com/baeldung/java8/Java8SortUnitTest.java
@@ -0,0 +1,210 @@
+package com.baeldung.java8;
+
+import com.baeldung.java8.entity.Human;
+import com.google.common.collect.Lists;
+import com.google.common.primitives.Ints;
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+import java.util.stream.Collectors;
+
+import static org.hamcrest.Matchers.equalTo;
+
+public class Java8SortUnitTest {
+
+ // tests -
+
+ @Test
+ public final void givenPreLambda_whenSortingEntitiesByName_thenCorrectlySorted() {
+ final List humans = Lists.newArrayList(new Human("Sarah", 10), new Human("Jack", 12));
+
+ Collections.sort(humans, new Comparator() {
+ @Override
+ public final int compare(final Human h1, final Human h2) {
+ return h1.getName().compareTo(h2.getName());
+ }
+ });
+
+ Assert.assertThat(humans.get(0), equalTo(new Human("Jack", 12)));
+ }
+
+ @Test
+ public final void whenSortingEntitiesByName_thenCorrectlySorted() {
+ final List humans = Lists.newArrayList(new Human("Sarah", 10), new Human("Jack", 12));
+
+ humans.sort((final Human h1, final Human h2) -> h1.getName().compareTo(h2.getName()));
+
+ Assert.assertThat(humans.get(0), equalTo(new Human("Jack", 12)));
+ }
+
+ @Test
+ public final void givenLambdaShortForm_whenSortingEntitiesByName_thenCorrectlySorted() {
+ final List humans = Lists.newArrayList(new Human("Sarah", 10), new Human("Jack", 12));
+
+ humans.sort((h1, h2) -> h1.getName().compareTo(h2.getName()));
+
+ Assert.assertThat(humans.get(0), equalTo(new Human("Jack", 12)));
+ }
+
+ @Test
+ public final void whenSortingEntitiesByNameThenAge_thenCorrectlySorted() {
+ final List humans = Lists.newArrayList(new Human("Sarah", 12), new Human("Sarah", 10), new Human("Zack", 12));
+ humans.sort((lhs, rhs) -> {
+ if (lhs.getName().equals(rhs.getName())) {
+ return Integer.compare(lhs.getAge(), rhs.getAge());
+ } else {
+ return lhs.getName().compareTo(rhs.getName());
+ }
+ });
+ Assert.assertThat(humans.get(0), equalTo(new Human("Sarah", 10)));
+ }
+
+ @Test
+ public final void givenCompositionVerbose_whenSortingEntitiesByNameThenAge_thenCorrectlySorted() {
+ final List humans = Lists.newArrayList(new Human("Sarah", 12), new Human("Sarah", 10), new Human("Zack", 12));
+ final Comparator byName = (h1, h2) -> h1.getName().compareTo(h2.getName());
+ final Comparator byAge = (h1, h2) -> Ints.compare(h1.getAge(), h2.getAge());
+
+ humans.sort(byName.thenComparing(byAge));
+ Assert.assertThat(humans.get(0), equalTo(new Human("Sarah", 10)));
+ }
+
+ @Test
+ public final void givenComposition_whenSortingEntitiesByNameThenAge_thenCorrectlySorted() {
+ final List humans = Lists.newArrayList(new Human("Sarah", 12), new Human("Sarah", 10), new Human("Zack", 12));
+
+ humans.sort(Comparator.comparing(Human::getName).thenComparing(Human::getAge));
+ Assert.assertThat(humans.get(0), equalTo(new Human("Sarah", 10)));
+ }
+
+ @Test
+ public final void whenSortingEntitiesByAge_thenCorrectlySorted() {
+ final List humans = Lists.newArrayList(new Human("Sarah", 10), new Human("Jack", 12));
+
+ humans.sort((h1, h2) -> Ints.compare(h1.getAge(), h2.getAge()));
+ Assert.assertThat(humans.get(0), equalTo(new Human("Sarah", 10)));
+ }
+
+ @Test
+ public final void whenSortingEntitiesByNameReversed_thenCorrectlySorted() {
+ final List humans = Lists.newArrayList(new Human("Sarah", 10), new Human("Jack", 12));
+ final Comparator comparator = (h1, h2) -> h1.getName().compareTo(h2.getName());
+
+ humans.sort(comparator.reversed());
+ Assert.assertThat(humans.get(0), equalTo(new Human("Sarah", 10)));
+ }
+
+ @Test
+ public final void givenMethodDefinition_whenSortingEntitiesByNameThenAge_thenCorrectlySorted() {
+ final List humans = Lists.newArrayList(new Human("Sarah", 10), new Human("Jack", 12));
+
+ humans.sort(Human::compareByNameThenAge);
+ Assert.assertThat(humans.get(0), equalTo(new Human("Jack", 12)));
+ }
+
+ @Test
+ public final void givenInstanceMethod_whenSortingEntitiesByName_thenCorrectlySorted() {
+ final List humans = Lists.newArrayList(new Human("Sarah", 10), new Human("Jack", 12));
+
+ humans.sort(Comparator.comparing(Human::getName));
+ Assert.assertThat(humans.get(0), equalTo(new Human("Jack", 12)));
+ }
+
+ @Test
+ public final void givenStreamNaturalOrdering_whenSortingEntitiesByName_thenCorrectlySorted() {
+ final List letters = Lists.newArrayList("B", "A", "C");
+
+ final List sortedLetters = letters.stream().sorted().collect(Collectors.toList());
+ Assert.assertThat(sortedLetters.get(0), equalTo("A"));
+ }
+
+ @Test
+ public final void givenStreamCustomOrdering_whenSortingEntitiesByName_thenCorrectlySorted() {
+ final List humans = Lists.newArrayList(new Human("Sarah", 10), new Human("Jack", 12));
+ final Comparator nameComparator = (h1, h2) -> h1.getName().compareTo(h2.getName());
+
+ final List sortedHumans = humans.stream().sorted(nameComparator).collect(Collectors.toList());
+ Assert.assertThat(sortedHumans.get(0), equalTo(new Human("Jack", 12)));
+ }
+
+ @Test
+ public final void givenStreamComparatorOrdering_whenSortingEntitiesByName_thenCorrectlySorted() {
+ final List humans = Lists.newArrayList(new Human("Sarah", 10), new Human("Jack", 12));
+
+ final List sortedHumans = humans.stream().sorted(Comparator.comparing(Human::getName)).collect(Collectors.toList());
+ Assert.assertThat(sortedHumans.get(0), equalTo(new Human("Jack", 12)));
+ }
+
+ @Test
+ public final void givenStreamNaturalOrdering_whenSortingEntitiesByNameReversed_thenCorrectlySorted() {
+ final List letters = Lists.newArrayList("B", "A", "C");
+
+ final List reverseSortedLetters = letters.stream().sorted(Comparator.reverseOrder()).collect(Collectors.toList());
+ Assert.assertThat(reverseSortedLetters.get(0), equalTo("C"));
+ }
+
+ @Test
+ public final void givenStreamCustomOrdering_whenSortingEntitiesByNameReversed_thenCorrectlySorted() {
+ final List humans = Lists.newArrayList(new Human("Sarah", 10), new Human("Jack", 12));
+ final Comparator reverseNameComparator = (h1, h2) -> h2.getName().compareTo(h1.getName());
+
+ final List reverseSortedHumans = humans.stream().sorted(reverseNameComparator).collect(Collectors.toList());
+ Assert.assertThat(reverseSortedHumans.get(0), equalTo(new Human("Sarah", 10)));
+ }
+
+ @Test
+ public final void givenStreamComparatorOrdering_whenSortingEntitiesByNameReversed_thenCorrectlySorted() {
+ final List humans = Lists.newArrayList(new Human("Sarah", 10), new Human("Jack", 12));
+
+ final List reverseSortedHumans = humans.stream().sorted(Comparator.comparing(Human::getName, Comparator.reverseOrder())).collect(Collectors.toList());
+ Assert.assertThat(reverseSortedHumans.get(0), equalTo(new Human("Sarah", 10)));
+ }
+
+ @Test(expected = NullPointerException.class)
+ public final void givenANullElement_whenSortingEntitiesByName_thenThrowsNPE() {
+ final List humans = Lists.newArrayList(null, new Human("Jack", 12));
+
+ humans.sort((h1, h2) -> h1.getName().compareTo(h2.getName()));
+ }
+
+ @Test
+ public final void givenANullElement_whenSortingEntitiesByNameManually_thenMovesTheNullToLast() {
+ final List humans = Lists.newArrayList(null, new Human("Jack", 12), null);
+
+ humans.sort((h1, h2) -> {
+ if (h1 == null) return h2 == null ? 0 : 1;
+ else if (h2 == null) return -1;
+
+ return h1.getName().compareTo(h2.getName());
+ });
+
+ Assert.assertNotNull(humans.get(0));
+ Assert.assertNull(humans.get(1));
+ Assert.assertNull(humans.get(2));
+ }
+
+ @Test
+ public final void givenANullElement_whenSortingEntitiesByName_thenMovesTheNullToLast() {
+ final List humans = Lists.newArrayList(null, new Human("Jack", 12), null);
+
+ humans.sort(Comparator.nullsLast(Comparator.comparing(Human::getName)));
+
+ Assert.assertNotNull(humans.get(0));
+ Assert.assertNull(humans.get(1));
+ Assert.assertNull(humans.get(2));
+ }
+
+ @Test
+ public final void givenANullElement_whenSortingEntitiesByName_thenMovesTheNullToStart() {
+ final List humans = Lists.newArrayList(null, new Human("Jack", 12), null);
+
+ humans.sort(Comparator.nullsFirst(Comparator.comparing(Human::getName)));
+
+ Assert.assertNull(humans.get(0));
+ Assert.assertNull(humans.get(1));
+ Assert.assertNotNull(humans.get(2));
+ }
+}
diff --git a/core-java-modules/core-java-lambdas/src/test/java/com/baeldung/java8/lambda/exceptions/LambdaExceptionWrappersUnitTest.java b/core-java-modules/core-java-lambdas/src/test/java/com/baeldung/java8/lambda/exceptions/LambdaExceptionWrappersUnitTest.java
new file mode 100644
index 0000000000..fe10266043
--- /dev/null
+++ b/core-java-modules/core-java-lambdas/src/test/java/com/baeldung/java8/lambda/exceptions/LambdaExceptionWrappersUnitTest.java
@@ -0,0 +1,50 @@
+package com.baeldung.java8.lambda.exceptions;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.List;
+
+import static com.baeldung.java8.lambda.exceptions.LambdaExceptionWrappers.*;
+
+public class LambdaExceptionWrappersUnitTest {
+
+ private static final Logger LOG = LoggerFactory.getLogger(LambdaExceptionWrappersUnitTest.class);
+
+ private List integers;
+
+ @Before
+ public void init() {
+ integers = Arrays.asList(3, 9, 7, 0, 10, 20);
+ }
+
+ @Test
+ public void whenNoExceptionFromLambdaWrapper_thenSuccess() {
+ integers.forEach(lambdaWrapper(i -> LOG.debug("{}", 50 / i)));
+ }
+
+ @Test
+ public void whenNoExceptionFromConsumerWrapper_thenSuccess() {
+ integers.forEach(consumerWrapper(i -> LOG.debug("{}", 50 / i), ArithmeticException.class));
+ }
+
+ @Test(expected = RuntimeException.class)
+ public void whenExceptionFromThrowingConsumerWrapper_thenSuccess() {
+ integers.forEach(throwingConsumerWrapper(i -> writeToFile(i)));
+ }
+
+ @Test
+ public void whenNoExceptionFromHandlingConsumerWrapper_thenSuccess() {
+ integers.forEach(handlingConsumerWrapper(i -> writeToFile(i), IOException.class));
+ }
+
+ private void writeToFile(Integer i) throws IOException {
+ if (i == 0) {
+ throw new IOException(); // mock IOException
+ }
+ }
+}
diff --git a/core-java-modules/core-java-lambdas/src/test/java/com/baeldung/java8/lambda/methodreference/Bicycle.java b/core-java-modules/core-java-lambdas/src/test/java/com/baeldung/java8/lambda/methodreference/Bicycle.java
new file mode 100644
index 0000000000..26f9f8bc46
--- /dev/null
+++ b/core-java-modules/core-java-lambdas/src/test/java/com/baeldung/java8/lambda/methodreference/Bicycle.java
@@ -0,0 +1,34 @@
+package com.baeldung.java8.lambda.methodreference;
+
+public class Bicycle {
+
+ private String brand;
+ private Integer frameSize;
+
+ public Bicycle(String brand) {
+ this.brand = brand;
+ this.frameSize = 0;
+ }
+
+ public Bicycle(String brand, Integer frameSize) {
+ this.brand = brand;
+ this.frameSize = frameSize;
+ }
+
+ public String getBrand() {
+ return brand;
+ }
+
+ public void setBrand(String brand) {
+ this.brand = brand;
+ }
+
+ public Integer getFrameSize() {
+ return frameSize;
+ }
+
+ public void setFrameSize(Integer frameSize) {
+ this.frameSize = frameSize;
+ }
+
+}
diff --git a/core-java-modules/core-java-lambdas/src/test/java/com/baeldung/java8/lambda/methodreference/BicycleComparator.java b/core-java-modules/core-java-lambdas/src/test/java/com/baeldung/java8/lambda/methodreference/BicycleComparator.java
new file mode 100644
index 0000000000..153a7d105a
--- /dev/null
+++ b/core-java-modules/core-java-lambdas/src/test/java/com/baeldung/java8/lambda/methodreference/BicycleComparator.java
@@ -0,0 +1,13 @@
+package com.baeldung.java8.lambda.methodreference;
+
+import java.util.Comparator;
+
+public class BicycleComparator implements Comparator {
+
+ @Override
+ public int compare(Bicycle a, Bicycle b) {
+ return a.getFrameSize()
+ .compareTo(b.getFrameSize());
+ }
+
+}
diff --git a/core-java-modules/core-java-lambdas/src/test/java/com/baeldung/java8/lambda/methodreference/MethodReferenceUnitTest.java b/core-java-modules/core-java-lambdas/src/test/java/com/baeldung/java8/lambda/methodreference/MethodReferenceUnitTest.java
new file mode 100644
index 0000000000..87c01c3ded
--- /dev/null
+++ b/core-java-modules/core-java-lambdas/src/test/java/com/baeldung/java8/lambda/methodreference/MethodReferenceUnitTest.java
@@ -0,0 +1,79 @@
+package com.baeldung.java8.lambda.methodreference;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.function.BiFunction;
+
+import org.apache.commons.lang3.StringUtils;
+import org.junit.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class MethodReferenceUnitTest {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(MethodReferenceUnitTest.class);
+
+ private static void doNothingAtAll(Object... o) {
+ }
+
+ @Test
+ public void referenceToStaticMethod() {
+ List messages = Arrays.asList("Hello", "Baeldung", "readers!");
+ messages.forEach(word -> StringUtils.capitalize(word));
+ messages.forEach(StringUtils::capitalize);
+ }
+
+ @Test
+ public void referenceToInstanceMethodOfParticularObject() {
+ BicycleComparator bikeFrameSizeComparator = new BicycleComparator();
+ createBicyclesList().stream()
+ .sorted((a, b) -> bikeFrameSizeComparator.compare(a, b));
+ createBicyclesList().stream()
+ .sorted(bikeFrameSizeComparator::compare);
+ }
+
+ @Test
+ public void referenceToInstanceMethodOfArbitratyObjectOfParticularType() {
+ List numbers = Arrays.asList(5, 3, 50, 24, 40, 2, 9, 18);
+ numbers.stream()
+ .sorted((a, b) -> a.compareTo(b));
+ numbers.stream()
+ .sorted(Integer::compareTo);
+ }
+
+ @Test
+ public void referenceToConstructor() {
+ BiFunction bikeCreator = (brand, frameSize) -> new Bicycle(brand, frameSize);
+ BiFunction bikeCreatorMethodReference = Bicycle::new;
+ List bikes = new ArrayList<>();
+ bikes.add(bikeCreator.apply("Giant", 50));
+ bikes.add(bikeCreator.apply("Scott", 20));
+ bikes.add(bikeCreatorMethodReference.apply("Trek", 35));
+ bikes.add(bikeCreatorMethodReference.apply("GT", 40));
+ }
+
+ @Test
+ public void referenceToConstructorSimpleExample() {
+ List bikeBrands = Arrays.asList("Giant", "Scott", "Trek", "GT");
+ bikeBrands.stream()
+ .map(Bicycle::new)
+ .toArray(Bicycle[]::new);
+ }
+
+ @Test
+ public void limitationsAndAdditionalExamples() {
+ createBicyclesList().forEach(b -> LOGGER.debug("Bike brand is '{}' and frame size is '{}'", b.getBrand(), b.getFrameSize()));
+ createBicyclesList().forEach((o) -> MethodReferenceUnitTest.doNothingAtAll(o));
+ }
+
+ private List createBicyclesList() {
+ List bikes = new ArrayList<>();
+ bikes.add(new Bicycle("Giant", 50));
+ bikes.add(new Bicycle("Scott", 20));
+ bikes.add(new Bicycle("Trek", 35));
+ bikes.add(new Bicycle("GT", 40));
+ return bikes;
+ }
+
+}
diff --git a/core-java-modules/core-java-lambdas/src/test/java/com/baeldung/java8/lambda/tips/Java8FunctionalInteracesLambdasUnitTest.java b/core-java-modules/core-java-lambdas/src/test/java/com/baeldung/java8/lambda/tips/Java8FunctionalInteracesLambdasUnitTest.java
new file mode 100644
index 0000000000..acc3bc8fa3
--- /dev/null
+++ b/core-java-modules/core-java-lambdas/src/test/java/com/baeldung/java8/lambda/tips/Java8FunctionalInteracesLambdasUnitTest.java
@@ -0,0 +1,94 @@
+package com.baeldung.java8.lambda.tips;
+
+import com.baeldung.java8.lambda.tips.Foo;
+import com.baeldung.java8.lambda.tips.FooExtended;
+import com.baeldung.java8.lambda.tips.UseFoo;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.util.function.Function;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+
+public class Java8FunctionalInteracesLambdasUnitTest {
+
+ private UseFoo useFoo;
+
+ @Before
+ public void init() {
+ useFoo = new UseFoo();
+ }
+
+ @Test
+ public void functionalInterfaceInstantiation_whenReturnDefiniteString_thenCorrect() {
+ final Foo foo = parameter -> parameter + "from lambda";
+ final String result = useFoo.add("Message ", foo);
+
+ assertEquals("Message from lambda", result);
+ }
+
+ @Test
+ public void standardFIParameter_whenReturnDefiniteString_thenCorrect() {
+ final Function fn = parameter -> parameter + "from lambda";
+ final String result = useFoo.addWithStandardFI("Message ", fn);
+
+ assertEquals("Message from lambda", result);
+ }
+
+ @Test
+ public void defaultMethodFromExtendedInterface_whenReturnDefiniteString_thenCorrect() {
+ final FooExtended fooExtended = string -> string;
+ final String result = fooExtended.defaultCommon();
+
+ assertEquals("Default Common from Bar", result);
+ }
+
+ @Test
+ public void lambdaAndInnerClassInstantiation_whenReturnSameString_thenCorrect() {
+ final Foo foo = parameter -> parameter + "from Foo";
+
+ final Foo fooByIC = new Foo() {
+ @Override
+ public String method(final String string) {
+ return string + "from Foo";
+ }
+ };
+
+ assertEquals(foo.method("Something "), fooByIC.method("Something "));
+ }
+
+ @Test
+ public void accessVariablesFromDifferentScopes_whenReturnPredefinedString_thenCorrect() {
+ assertEquals("Results: resultIC = Inner class value, resultLambda = Enclosing scope value", useFoo.scopeExperiment());
+ }
+
+ @Test
+ public void shorteningLambdas_whenReturnEqualsResults_thenCorrect() {
+ final Foo foo = parameter -> buildString(parameter);
+
+ final Foo fooHuge = parameter -> {
+ final String result = "Something " + parameter;
+ // many lines of code
+ return result;
+ };
+
+ assertEquals(foo.method("Something"), fooHuge.method("Something"));
+ }
+
+ private String buildString(final String parameter) {
+ final String result = "Something " + parameter;
+ // many lines of code
+ return result;
+ }
+
+ @Test
+ public void mutatingOfEffectivelyFinalVariable_whenNotEquals_thenCorrect() {
+ final int[] total = new int[1];
+ final Runnable r = () -> total[0]++;
+ r.run();
+
+ assertNotEquals(0, total[0]);
+ }
+
+}
diff --git a/core-java-modules/pom.xml b/core-java-modules/pom.xml
index cfb968235b..ade1ebdbd8 100644
--- a/core-java-modules/pom.xml
+++ b/core-java-modules/pom.xml
@@ -32,6 +32,7 @@
core-java-datetime-conversion
core-java-io
core-java-io-2
+ core-java-lambdas
core-java-serialization
core-java-streams
core-java-streams