diff --git a/javaslang/pom.xml b/javaslang/pom.xml
new file mode 100644
index 0000000000..fecbeeea4f
--- /dev/null
+++ b/javaslang/pom.xml
@@ -0,0 +1,41 @@
+
+ 4.0.0
+ com.baeldung
+ Javaslang
+ 1.0
+ Javaslang
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ 3.3
+
+ 1.8
+ 1.8
+
+
+
+
+
+
+ junit
+ junit
+ 4.12
+ test
+
+
+ org.hamcrest
+ hamcrest-all
+ 1.3
+
+
+ io.javaslang
+ javaslang
+ 2.1.0-alpha
+
+
+
+
+
diff --git a/javaslang/src/main/java/com/baeldung/javaslang/Person.java b/javaslang/src/main/java/com/baeldung/javaslang/Person.java
new file mode 100644
index 0000000000..38a6603f98
--- /dev/null
+++ b/javaslang/src/main/java/com/baeldung/javaslang/Person.java
@@ -0,0 +1,38 @@
+package com.baeldung.javaslang;
+
+public class Person {
+ private String name;
+ private int age;
+
+ public Person(String name, int age) {
+ super();
+ this.name = name;
+ this.age = age;
+ }
+
+ public Person() {
+ super();
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public int getAge() {
+ return age;
+ }
+
+ public void setAge(int age) {
+ this.age = age;
+ }
+
+ @Override
+ public String toString() {
+ return "Person [name=" + name + ", age=" + age + "]";
+ }
+
+}
diff --git a/javaslang/src/main/java/com/baeldung/javaslang/PersonValidator.java b/javaslang/src/main/java/com/baeldung/javaslang/PersonValidator.java
new file mode 100644
index 0000000000..fb30d6072c
--- /dev/null
+++ b/javaslang/src/main/java/com/baeldung/javaslang/PersonValidator.java
@@ -0,0 +1,22 @@
+package com.baeldung.javaslang;
+
+import javaslang.collection.List;
+import javaslang.control.Validation;
+
+class PersonValidator {
+ String NAME_ERR = "Invalid characters in name: ";
+ String AGE_ERR = "Age must be at least 0";
+
+ public Validation, Person> validatePerson(String name, int age) {
+ return Validation.combine(validateName(name), validateAge(age)).ap(Person::new);
+ }
+
+ private Validation validateName(String name) {
+ String invalidChars = name.replaceAll("[a-zA-Z ]", "");
+ return invalidChars.isEmpty() ? Validation.valid(name) : Validation.invalid(NAME_ERR + invalidChars);
+ }
+
+ private Validation validateAge(int age) {
+ return age < 0 ? Validation.invalid(AGE_ERR) : Validation.valid(age);
+ }
+}
diff --git a/javaslang/src/test/java/com/baeldung/javaslang/JavaSlangTest.java b/javaslang/src/test/java/com/baeldung/javaslang/JavaSlangTest.java
new file mode 100644
index 0000000000..ecba894723
--- /dev/null
+++ b/javaslang/src/test/java/com/baeldung/javaslang/JavaSlangTest.java
@@ -0,0 +1,338 @@
+package com.baeldung.javaslang;
+
+import static javaslang.API.$;
+import static javaslang.API.Case;
+import static javaslang.API.Match;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.function.BiFunction;
+import java.util.function.Function;
+import java.util.stream.IntStream;
+
+import org.junit.Test;
+
+import javaslang.Function0;
+import javaslang.Function1;
+import javaslang.Function2;
+import javaslang.Function5;
+import javaslang.Lazy;
+import javaslang.Tuple;
+import javaslang.Tuple2;
+import javaslang.Tuple3;
+import javaslang.collection.List;
+import javaslang.control.Option;
+import javaslang.control.Try;
+import javaslang.control.Validation;
+
+public class JavaSlangTest {
+ @Test
+ public void givenList_whenSorts_thenCorrect() {
+ List sortedList = List.of(3, 2, 1).sorted();
+ }
+
+ /*
+ * Tuples
+ */
+ // creating and element access
+ @Test
+ public void whenCreatesTuple_thenCorrect1() {
+ Tuple2 java8 = Tuple.of("Java", 8);
+ String element1 = java8._1;
+ int element2 = java8._2();
+
+ assertEquals("Java", element1);
+ assertEquals(8, element2);
+ }
+
+ @Test
+ public void whenCreatesTuple_thenCorrect2() {
+ Tuple3 java8 = Tuple.of("Java", 8, 1.8);
+ String element1 = java8._1;
+ int element2 = java8._2();
+ double element3 = java8._3();
+
+ assertEquals("Java", element1);
+ assertEquals(8, element2);
+ assertEquals(1.8, element3, 0.1);
+ }
+
+ // mapping--component-wise(using Function interface)
+ @Test
+ public void givenTuple_whenMapsComponentWise_thenCorrect() {
+ Tuple2 java8 = Tuple.of("Java", 8);
+ Tuple2 mapOfJava8 = java8.map(s -> s + "slang", i -> i / 2);
+ int num = mapOfJava8._2();
+ assertEquals("Javaslang", mapOfJava8._1);
+
+ assertEquals(4, num);
+
+ }
+
+ // mapping--with one mapper(using BiFunction interface)
+ @Test
+ public void givenTuple_whenMapsWithOneMapper_thenCorrect() {
+ Tuple2 java8 = Tuple.of("Java", 8);
+ Tuple2 mapOfJava8 = java8.map((s, i) -> Tuple.of(s + "slang", i / 2));
+ int num = mapOfJava8._2();
+ assertEquals("Javaslang", mapOfJava8._1);
+
+ assertEquals(4, num);
+ }
+
+ // transforming a tuple
+ @Test
+ public void givenTuple_whenTransforms_thenCorrect() {
+ Tuple2 java8 = Tuple.of("Java", 8);
+ String transformed = java8.apply((s, i) -> s + "slang " + i / 2);
+ assertEquals("Javaslang 4", transformed);
+ }
+
+ /*
+ * Functions
+ */
+ @Test
+ public void givenJava8Function_whenWorks_thenCorrect() {
+ Function square = (num) -> num * num;
+ int result = square.apply(2);
+ assertEquals(4, result);
+ }
+
+ @Test
+ public void givenJava8BiFunction_whenWorks_thenCorrect() {
+ BiFunction sum = (num1, num2) -> num1 + num2;
+ int result = sum.apply(5, 7);
+ assertEquals(12, result);
+ }
+
+ @Test
+ public void givenJavaslangFunction_whenWorks_thenCorrect() {
+ Function1 square = (num) -> num * num;
+ Integer result = square.apply(2);
+ assertEquals(Integer.valueOf(4), result);
+ }
+
+ @Test
+ public void givenJavaslangBiFunction_whenWorks_thenCorrect() {
+ Function2 sum = (num1, num2) -> num1 + num2;
+ Integer result = sum.apply(5, 7);
+ assertEquals(Integer.valueOf(12), result);
+ }
+
+ @Test
+ public void whenCreatesFunction_thenCorrect0() {
+ Function0 getClazzName = () -> this.getClass().getName();
+ String clazzName = getClazzName.apply();
+ assertEquals("com.baeldung.javaslang.JavaSlangTest", clazzName);
+ }
+
+ @Test
+ public void whenCreatesFunction_thenCorrect2() {
+ Function2 sum = (a, b) -> a + b;
+ int summed = sum.apply(5, 6);
+ assertEquals(11, summed);
+ }
+
+ @Test
+ public void whenCreatesFunction_thenCorrect5() {
+ Function5 concat = (a, b, c, d, e) -> a + b + c + d + e;
+ String finalString = concat.apply("Hello ", "world", "! ", "Learn ", "Javaslang");
+ assertEquals("Hello world! Learn Javaslang", finalString);
+ }
+
+ @Test
+ public void whenCreatesFunctionFromMethodRef_thenCorrect() {
+ Function2 sum = Function2.of(this::sum);
+ int summed = sum.apply(5, 6);
+ assertEquals(11, summed);
+ }
+
+ public int sum(int a, int b) {
+ return a + b;
+ }
+
+
+ /*
+ * Values
+ */
+ // option
+ @Test
+ public void givenValue_whenNullCheckNeeded_thenCorrect() {
+ Object possibleNullObj = null;
+ if (possibleNullObj == null)
+ possibleNullObj = "someDefaultValue";
+ assertNotNull(possibleNullObj);
+ }
+
+ @Test(expected = NullPointerException.class)
+ public void givenValue_whenNullCheckNeeded_thenCorrect2() {
+ Object possibleNullObj = null;
+ assertEquals("somevalue", possibleNullObj.toString());
+ }
+
+ @Test
+ public void givenValue_whenCreatesOption_thenCorrect() {
+ Option