diff --git a/src/test/java/lambda/part3/exercise/FilterMap.java b/src/test/java/lambda/part3/exercise/FilterMap.java index 178190e..a39af6c 100644 --- a/src/test/java/lambda/part3/exercise/FilterMap.java +++ b/src/test/java/lambda/part3/exercise/FilterMap.java @@ -1,10 +1,21 @@ package lambda.part3.exercise; +import data.Employee; +import data.JobHistoryEntry; +import data.Person; +import org.junit.Test; + import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; import java.util.List; import java.util.function.Function; import java.util.function.Predicate; +import static lambda.part3.exercise.Mapping.addOneYear; +import static lambda.part3.exercise.Mapping.changeToQa; +import static org.junit.Assert.assertEquals; + public class FilterMap { public static class Container { @@ -32,31 +43,95 @@ public Function getFunction() { public static class LazyCollectionHelper { private final List> actions; - private final List list; + private final List list; - public LazyCollectionHelper(List list, List> actions) { + private LazyCollectionHelper(List list, List> actions) { this.actions = actions; this.list = list; } public LazyCollectionHelper(List list) { - this(list, new ArrayList<>()); + this( list, new ArrayList<>()); } public LazyCollectionHelper filter(Predicate condition) { - List> newActions = new ArrayList<>(actions); - newActions.add(new Container<>((Predicate) condition)); - return new LazyCollectionHelper<>(list, newActions); + actions.add(new Container<>((Predicate) condition)); + return this; } public LazyCollectionHelper map(Function function) { - // TODO - throw new UnsupportedOperationException(); + actions.add(new Container<>((Function) function)); + return new LazyCollectionHelper(list, actions); } public List force() { - // TODO - throw new UnsupportedOperationException(); + List result = new ArrayList<>(list); + for (Container action : actions) { + List tmp = new ArrayList<>(); + if (action.getFunction() != null) + result.forEach(element -> + tmp.add(action.getFunction().apply(element))); + else result.forEach(element -> { + if (action.getPredicate().test(element)) + tmp.add(element); + }); + result = tmp; + } + final ArrayList ret = new ArrayList<>(); + result.forEach(e -> ret.add((T) e)); + return ret; } } + + @Test + public void createEmployeesAndGetEpamEmployeesHistory() { + final List employees = + Arrays.asList( + new Employee( + new Person("a", "Galt", 30), + Arrays.asList( + new JobHistoryEntry(2, "dev", "epam"), + new JobHistoryEntry(1, "dev", "google") + )), + new Employee( + new Person("b", "Doe", 40), + Arrays.asList( + new JobHistoryEntry(3, "qa", "yandex"), + new JobHistoryEntry(1, "qa", "epam"), + new JobHistoryEntry(1, "dev", "abc") + )), + new Employee( + new Person("c", "White", 50), + Collections.singletonList( + new JobHistoryEntry(5, "qa", "JoshkinaLolo") + )) + ); + + final List mappedEmployees = + new LazyCollectionHelper(employees) + .map(e -> ((Employee)e).withPerson(((Employee)e).getPerson().withFirstName("John"))) + .map(e -> ((Employee)e).withJobHistory(addOneYear(((Employee)e).getJobHistory()))) + .map(e -> ((Employee)e).withJobHistory(changeToQa(((Employee)e).getJobHistory()))) + .filter(e -> ((Employee)e).getJobHistory().stream().anyMatch(j -> j.getEmployer().equals("epam"))) + .force(); + + final List expectedResult = + Arrays.asList( + new Employee( + new Person("John", "Galt", 30), + Arrays.asList( + new JobHistoryEntry(3, "dev", "epam"), + new JobHistoryEntry(2, "dev", "google") + )), + new Employee( + new Person("John", "Doe", 40), + Arrays.asList( + new JobHistoryEntry(4, "QA", "yandex"), + new JobHistoryEntry(2, "QA", "epam"), + new JobHistoryEntry(2, "dev", "abc") + )) + ); + + assertEquals(mappedEmployees, expectedResult); + } } diff --git a/src/test/java/lambda/part3/exercise/Mapping.java b/src/test/java/lambda/part3/exercise/Mapping.java index c0a814a..1dd337d 100644 --- a/src/test/java/lambda/part3/exercise/Mapping.java +++ b/src/test/java/lambda/part3/exercise/Mapping.java @@ -9,10 +9,7 @@ import java.util.Arrays; import java.util.Collections; import java.util.List; -import java.util.function.BiConsumer; -import java.util.function.Consumer; import java.util.function.Function; -import java.util.function.Predicate; import static org.junit.Assert.assertEquals; @@ -33,7 +30,9 @@ public List getList() { // [T1, T2, T3] -> (T -> R) -> [R1, R2, R3] public MapHelper map(Function f) { // TODO - throw new UnsupportedOperationException(); + final ArrayList result = new ArrayList<>(); + this.list.forEach(e -> result.add(f.apply(e))); + return new MapHelper<>(result); } // [T] -> (T -> [R]) -> [R] @@ -46,10 +45,22 @@ public MapHelper flatMap(Function> f) { f.apply(t).forEach(result::add) ); - return new MapHelper(result); + return new MapHelper<>(result); } } + public static List addOneYear(List list){ + return new MapHelper<>(list) + .map(e -> e.withDuration(e.getDuration() + 1) ).getList(); + } + + public static List changeToQa(List list) { + return new MapHelper<>(list) + .map(e -> e.getPosition().equals("qa") ? + e.withPosition("QA") : e) + .getList(); + } + @Test public void mapping() { final List employees = @@ -76,12 +87,15 @@ public void mapping() { final List mappedEmployees = new MapHelper<>(employees) - /* - .map(TODO) // change name to John .map(e -> e.withPerson(e.getPerson().withFirstName("John"))) - .map(TODO) // add 1 year to experience duration .map(e -> e.withJobHistory(addOneYear(e.getJobHistory()))) - .map(TODO) // replace qa with QA - * */ - .getList(); + /* + .map(TODO) // change name to John .map(e -> e.withPerson(e.getPerson().withFirstName("John"))) + .map(TODO) // add 1 year to experience duration .map(e -> e.withJobHistory(addOneYear(e.getJobHistory()))) + .map(TODO) // replace qa with QA + * */ + .map(e -> e.withPerson(e.getPerson().withFirstName("John"))) + .map(e -> e.withJobHistory(addOneYear(e.getJobHistory()))) + .map(e -> e.withJobHistory(changeToQa(e.getJobHistory()))) + .getList(); final List expectedResult = Arrays.asList( @@ -105,13 +119,16 @@ public void mapping() { )) ); - assertEquals(mappedEmployees, expectedResult); + assertEquals(expectedResult, mappedEmployees); } - private static class LazyMapHelper { + private List list; + private Function function; public LazyMapHelper(List list, Function function) { + this.list = list; + this.function = function; } public static LazyMapHelper from(List list) { @@ -119,54 +136,18 @@ public static LazyMapHelper from(List list) { } public List force() { - // TODO - throw new UnsupportedOperationException(); + if (function == null) throw new NullPointerException("Function is NULL"); + return new MapHelper<>(list) + .map(function) + .getList(); } public LazyMapHelper map(Function f) { - // TODO - throw new UnsupportedOperationException(); - } - - } - - private static class LazyFlatMapHelper { - - public LazyFlatMapHelper(List list, Function> function) { + return new LazyMapHelper<>(list, f.compose(function)); } - public static LazyFlatMapHelper from(List list) { - throw new UnsupportedOperationException(); - } - - public List force() { - // TODO - throw new UnsupportedOperationException(); - } - - // TODO filter - // (T -> boolean) -> (T -> [T]) - // filter: [T1, T2] -> (T -> boolean) -> [T2] - // flatMap": [T1, T2] -> (T -> [T]) -> [T2] - - public LazyFlatMapHelper map(Function f) { - final Function> listFunction = rR2TorListR2(f); - return flatMap(listFunction); - } - - // (R -> R2) -> (R -> [R2]) - private Function> rR2TorListR2(Function f) { - throw new UnsupportedOperationException(); - } - - // TODO * - public LazyFlatMapHelper flatMap(Function> f) { - throw new UnsupportedOperationException(); - } } - - @Test public void lazy_mapping() { final List employees = @@ -193,12 +174,15 @@ public void lazy_mapping() { final List mappedEmployees = LazyMapHelper.from(employees) - /* - .map(TODO) // change name to John - .map(TODO) // add 1 year to experience duration - .map(TODO) // replace qa with QA - * */ - .force(); + /* + .map(TODO) // change name to John + .map(TODO) // add 1 year to experience duration + .map(TODO) // replace qa with QA + * */ + .map(e -> e.withPerson(e.getPerson().withFirstName("John"))) + .map(e -> e.withJobHistory(addOneYear(e.getJobHistory()))) + .map(e -> e.withJobHistory(changeToQa(e.getJobHistory()))) + .force(); final List expectedResult = Arrays.asList( @@ -224,4 +208,6 @@ public void lazy_mapping() { assertEquals(mappedEmployees, expectedResult); } + + } diff --git a/src/test/java/lambda/part3/exercise/ReachIterableTest.java b/src/test/java/lambda/part3/exercise/ReachIterableTest.java new file mode 100644 index 0000000..51793fa --- /dev/null +++ b/src/test/java/lambda/part3/exercise/ReachIterableTest.java @@ -0,0 +1,227 @@ +package lambda.part3.exercise; + +import com.sun.xml.internal.bind.v2.runtime.unmarshaller.XsiNilLoader; +import data.Employee; +import data.JobHistoryEntry; +import data.Person; +import org.junit.Test; + +import java.util.*; +import java.util.function.Consumer; +import java.util.function.Function; +import java.util.function.Predicate; + +import static lambda.part3.exercise.Mapping.addOneYear; +import static lambda.part3.exercise.Mapping.changeToQa; +import static org.hamcrest.core.Is.is; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.assertFalse; + +/** + * Created by whobscr on 06.07.17. + */ +public class ReachIterableTest { + private interface ReachIterable { + + boolean tryGet(Consumer c); + + default ReachIterable map(Function f) { + return new ReachIterable() { + @Override + public boolean tryGet(Consumer c) { + return ReachIterable.this.tryGet(t -> c.accept(f.apply(t))); + } + }; + } + + default ReachIterable flatMap(Function> mapper) { + return new ReachIterable() { + @Override + public boolean tryGet(Consumer c) { + return ReachIterable.this.tryGet(e -> mapper.apply(e).tryGet(c)); + } + }; + } + + default ReachIterable filter(Predicate p) { + return new ReachIterable() { + @Override + public boolean tryGet(Consumer c) { + return ReachIterable.this.tryGet(e -> { + if (p.test(e)) c.accept(e); + }); + } + }; + } + + default List toList() { + final ArrayList ts = new ArrayList<>(); + while (tryGet(ts::add)); + return ts; + } + + default boolean allMatch(Predicate p) { + return !anyMatch(p.negate()); + } + + default boolean noneMatch(Predicate p) { + return anyMatch(p.negate()); + } + + default boolean anyMatch(Predicate p) { + return firstMatch(p).isPresent(); + } + + default Optional firstMatch(Predicate p) { + Map.Entry> curElem = + new AbstractMap.SimpleEntry<>(0, Optional.empty()); + while (tryGet(c -> curElem.setValue(Optional.of(c)))) { + if (curElem.getValue().isPresent() + && p.test(curElem.getValue().get())) + return Optional.of(curElem.getValue().get()); + } + return Optional.empty(); + } + } + + static ReachIterable from(Iterable iterable) { + return new ReachIterable() { + private Iterator iterator = iterable.iterator(); + + @Override + public boolean tryGet(Consumer action) { + if (iterator.hasNext()) { + action.accept(iterator.next()); + return true; + } else return false; + } + }; + } + + @Test + public void emptyArray() { + assertFalse(from(new ArrayList()) + .tryGet(c -> {})); + } + + @Test + public void fiveElementsArrayMapEven() { + List integers = new ArrayList<>(); + integers.add(1); integers.add(2); integers.add(3); + integers.add(4); integers.add(5); integers.add(6); + + final ReachIterable reachIterable = from(integers); + integers = reachIterable.map(c -> c % 2).toList(); + final ArrayList expected = new ArrayList<>(); + + expected.add(1); expected.add(0); expected.add(1); + expected.add(0); expected.add(1); expected.add(0); + assertThat(integers, is(expected)); + } + + @Test + public void fiveElementsArrayFilterEven() { + List integers = new ArrayList<>(); + integers.add(1); integers.add(2); integers.add(3); + integers.add(4); integers.add(5); integers.add(6); + + final ReachIterable reachIterable = from(integers); + integers = reachIterable.filter(c -> c % 2 == 0).toList(); + final ArrayList expected = new ArrayList<>(); + + expected.add(2); expected.add(4); expected.add(6); + assertThat(integers, is(expected)); + } + + @Test + public void trueNoneMatchGreaterThanFive() { + List integers = new ArrayList<>(); + integers.add(4); integers.add(2); integers.add(3); + integers.add(1); integers.add(5); + + assertTrue(from(integers) + .noneMatch(c -> c > 5)); + } + + @Test + public void trueAllMatchLessThanFive() { + List integers = new ArrayList<>(); + integers.add(4); integers.add(2); integers.add(5); + integers.add(1); integers.add(6); integers.add(3); + + assertTrue(from(integers) + .allMatch(c -> c < 7 && c > 0)); + } + + @Test + public void falseAllMatchLessThanFive() { + List integers = new ArrayList<>(); + integers.add(1); integers.add(2); integers.add(3); + integers.add(4); integers.add(5); integers.add(6); + + assertFalse(from(integers) + .allMatch(c -> c < 5)); + } + + @Test + public void mapping() { + final List employees = + Arrays.asList( + new Employee( + new Person("a", "Galt", 30), + Arrays.asList( + new JobHistoryEntry(2, "dev", "epam"), + new JobHistoryEntry(1, "dev", "google") + )), + new Employee( + new Person("b", "Doe", 40), + Arrays.asList( + new JobHistoryEntry(3, "qa", "yandex"), + new JobHistoryEntry(1, "qa", "epam"), + new JobHistoryEntry(1, "dev", "abc") + )), + new Employee( + new Person("c", "White", 50), + Collections.singletonList( + new JobHistoryEntry(5, "qa", "forForeach") + )) + ); + + final List result = + from(employees) + .map(e -> e.withPerson(e.getPerson().withFirstName("John"))) + .map(e -> e.withJobHistory(addOneYear(e.getJobHistory()))) + .map(e -> e.withJobHistory(changeToQa(e.getJobHistory()))) + .filter(e -> from(e.getJobHistory()).anyMatch(j -> j.getEmployer().equals("epam"))) + .toList(); + + final List expectedResult = + Arrays.asList( + new Employee( + new Person("John", "Galt", 30), + Arrays.asList( + new JobHistoryEntry(3, "dev", "epam"), + new JobHistoryEntry(2, "dev", "google") + )), + new Employee( + new Person("John", "Doe", 40), + Arrays.asList( + new JobHistoryEntry(4, "QA", "yandex"), + new JobHistoryEntry(2, "QA", "epam"), + new JobHistoryEntry(2, "dev", "abc") + )) + ); + assertThat(result, is(expectedResult)); + assertTrue(from(result) + .allMatch(e -> from(e.getJobHistory()) + .anyMatch(entry -> entry.getEmployer().equals("epam")))); + assertTrue(from(result) + .allMatch(e -> from(e.getJobHistory()) + .noneMatch(entry -> entry.getPosition().equals("qa")))); + assertFalse(from(result) + .anyMatch(e -> from(e.getJobHistory()) + .anyMatch(entry -> entry.getEmployer().equals("forForeach")))); + } +} diff --git a/src/test/java/lambda/part3/exercise/Traverser.java b/src/test/java/lambda/part3/exercise/Traverser.java new file mode 100644 index 0000000..ea6d944 --- /dev/null +++ b/src/test/java/lambda/part3/exercise/Traverser.java @@ -0,0 +1,161 @@ +package lambda.part3.exercise; + +import data.Employee; +import data.JobHistoryEntry; +import data.Person; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.function.Consumer; +import java.util.function.Function; +import java.util.function.Predicate; + +import static lambda.part3.exercise.Mapping.addOneYear; +import static lambda.part3.exercise.Mapping.changeToQa; +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertThat; + +/** + * Created by whobscr on 06.07.17. + */ +public class Traverser { + private interface Traversable { + void forEach(Consumer c); + + default Traversable map(Function f) { + return new Traversable() { + @Override + public void forEach(Consumer c) { + Traversable.this.forEach(t -> c.accept(f.apply(t))); + } + }; + } + + default Traversable flatMap(Function> mapper) { + return new Traversable() { + @Override + public void forEach(Consumer c) { + Traversable.this.forEach(e -> mapper.apply(e).forEach(c)); + } + }; + + } + + default Traversable filter(Predicate p) { + return new Traversable() { + @Override + public void forEach(Consumer c) { + Traversable.this.forEach(e -> { + if (p.test(e)) c.accept(e); + }); + } + }; + } + + default List toList() { + final ArrayList ts = new ArrayList<>(); + forEach(ts::add); + return ts; + } + } + + static Traversable from(List list) { + return new Traversable() { + @Override + public void forEach(Consumer action) { + list.forEach(action); + } + }; + } + + @Test + public void emptyArray() { + from(new ArrayList()).forEach(c -> {}); + } + + @Test + public void fiveElementsArrayMapEven() { + List integers = new ArrayList<>(); + integers.add(1); integers.add(2); integers.add(3); + integers.add(4); integers.add(5); integers.add(6); + + final Traversable reachIterable = from(integers); + integers = reachIterable.map(c -> c % 2).toList(); + final ArrayList expected = new ArrayList<>(); + + expected.add(1); expected.add(0); expected.add(1); + expected.add(0); expected.add(1); expected.add(0); + assertThat(integers, is(expected)); + } + + @Test + public void fiveElementsArrayFilterEven() { + List integers = new ArrayList<>(); + integers.add(1); integers.add(2); integers.add(3); + integers.add(4); integers.add(5); integers.add(6); + + final Traversable reachIterable = from(integers); + integers = reachIterable.filter(c -> c % 2 == 0).toList(); + final ArrayList expected = new ArrayList<>(); + + expected.add(2); expected.add(4); expected.add(6); + assertThat(integers, is(expected)); + } + + @Test + public void createEmployeesAndGetEpamEmployeesHistory() { + final List employees = + Arrays.asList( + new Employee( + new Person("a", "Galt", 30), + Arrays.asList( + new JobHistoryEntry(2, "dev", "epam"), + new JobHistoryEntry(1, "dev", "google") + )), + new Employee( + new Person("b", "Doe", 40), + Arrays.asList( + new JobHistoryEntry(3, "qa", "yandex"), + new JobHistoryEntry(1, "qa", "epam"), + new JobHistoryEntry(1, "dev", "abc") + )), + new Employee( + new Person("c", "White", 50), + Collections.singletonList( + new JobHistoryEntry(5, "qa", "JoshkinaLolo") + )) + ); + + final List mappedEmployees = + from(employees) + .map(e -> e.withPerson(e.getPerson().withFirstName("John"))) + .map(e -> e.withJobHistory(addOneYear(e.getJobHistory()))) + .map(e -> e.withJobHistory(changeToQa(e.getJobHistory()))) + .filter(e -> e.getJobHistory().stream().anyMatch(j -> j.getEmployer().equals("epam"))) + .toList(); + + final List expectedResult = + Arrays.asList( + new Employee( + new Person("John", "Galt", 30), + Arrays.asList( + new JobHistoryEntry(3, "dev", "epam"), + new JobHistoryEntry(2, "dev", "google") + )), + new Employee( + new Person("John", "Doe", 40), + Arrays.asList( + new JobHistoryEntry(4, "QA", "yandex"), + new JobHistoryEntry(2, "QA", "epam"), + new JobHistoryEntry(2, "dev", "abc") + )) + ); + + assertEquals(mappedEmployees, expectedResult); + } +}