diff --git a/src/test/java/part2/exercise/CollectorsExercise2.java b/src/test/java/part2/exercise/CollectorsExercise2.java index 00fda00..05276a3 100755 --- a/src/test/java/part2/exercise/CollectorsExercise2.java +++ b/src/test/java/part2/exercise/CollectorsExercise2.java @@ -1,8 +1,5 @@ package part2.exercise; -import data.Employee; -import data.JobHistoryEntry; -import data.Person; import org.junit.Test; import java.util.*; @@ -131,7 +128,7 @@ public Map> getKnownKeys() { } } - private static class MapPair { + public static class MapPair { private final Map keyById; private final Map> valueById; @@ -153,7 +150,7 @@ public Map> getValueById() { } } - private static > + public static > BinaryOperator mapMerger(BinaryOperator mergeFunction) { return (m1, m2) -> { for (Map.Entry e : m2.entrySet()) { diff --git a/src/test/java/part3/exercise/CollectorCombination.java b/src/test/java/part3/exercise/CollectorCombination.java index 15a42d5..fc1b4b3 100755 --- a/src/test/java/part3/exercise/CollectorCombination.java +++ b/src/test/java/part3/exercise/CollectorCombination.java @@ -3,14 +3,22 @@ import org.junit.Test; import part2.exercise.CollectorsExercise2; import part2.exercise.CollectorsExercise2.Key; +import part2.exercise.CollectorsExercise2.MapPair; import part2.exercise.CollectorsExercise2.Value; -import java.util.List; -import java.util.Map; +import java.util.*; +import java.util.function.BiConsumer; +import java.util.function.BinaryOperator; import java.util.function.Function; +import java.util.function.Supplier; import java.util.stream.Collector; -import static java.util.stream.Collectors.*; +import static java.util.stream.Collectors.groupingBy; +import static java.util.stream.Collectors.mapping; +import static java.util.stream.Collectors.toMap; +import static org.junit.Assert.assertEquals; +import static part2.exercise.CollectorsExercise2.generatePairs; +import static part2.exercise.CollectorsExercise2.mapMerger; public class CollectorCombination { @@ -34,8 +42,48 @@ public B getB() { private static Collector, Pair> paired(Collector c1, Collector c2) { - // TODO - throw new UnsupportedOperationException(); + + return new Collector, Pair>() { + @Override + public Supplier> supplier() { + return () -> new Pair<>(c1.supplier().get(), c2.supplier().get()); + } + + @Override + public BiConsumer, T> accumulator() { + return (m1M2Pair, t) -> { + c1.accumulator().accept(m1M2Pair.getA(), t); + c2.accumulator().accept(m1M2Pair.getB(), t); + }; + } + + @Override + public BinaryOperator> combiner() { + return (m1M2Pair1, m1M2Pair2) -> { + M1 m1 = c1.combiner().apply(m1M2Pair1.getA(), m1M2Pair2.getA()); + M2 m2 = c2.combiner().apply(m1M2Pair1.getB(), m1M2Pair2.getB()); + return new Pair<>(m1, m2); + }; + } + + @Override + public Function, Pair> finisher() { + return m1M2Pair -> { + R1 r1 = c1.finisher().apply(m1M2Pair.getA()); + R2 r2 = c2.finisher().apply(m1M2Pair.getB()); + return new Pair<>(r1, r2); + }; + } + + @Override + public Set characteristics() { + HashSet ch = new HashSet<>(); + ch.addAll(c1.characteristics()); + ch.addAll(c2.characteristics()); + + return ch; + } + }; } @Test @@ -44,10 +92,60 @@ public void collectKeyValueMap() { // В 1 проход в 2 Map с использованием MapPair и mapMerger // final MapPair res2 = pairs.stream() // .collect(new Collector() { + List pairs = generatePairs(10, 100); - // Перепишите решение в слещующем виде: - final List pairs = CollectorsExercise2.generatePairs(10, 100); + final MapPair res1 = + pairs.stream() + .collect(new Collector() { + @Override + public Supplier supplier() { + return MapPair::new; + } + + @Override + public BiConsumer accumulator() { + return (mapPair, pair) -> { + mapPair.getKeyById().putIfAbsent(pair.getKey().getId(), pair.getKey()); + mapPair.getValueById().computeIfAbsent(pair.getValue().getKeyId(), + s -> new ArrayList<>()).add(pair.getValue()); + }; + } + @Override + public BinaryOperator combiner() { + return (mapPair1, mapPair2) -> { + BinaryOperator> keyBinaryOperator = mapMerger((o, o2) -> o); + Map mapKeys = + keyBinaryOperator.apply(mapPair1.getKeyById(), mapPair2.getKeyById()); + + BinaryOperator>> valueBinaryOperator = + mapMerger( + (list1, list2) -> { + list1.addAll(list2); + return list1; + }); + Map> mapValues = + valueBinaryOperator.apply(mapPair1.getValueById(), mapPair2.getValueById()); + + return new MapPair(mapKeys, mapValues); + }; + } + + @Override + public Function finisher() { + return Function.identity(); + } + + @Override + public Set characteristics() { + return Collections.unmodifiableSet(EnumSet.of( + Characteristics.UNORDERED, + Collector.Characteristics.IDENTITY_FINISH)); + } + }); + + + // Перепишите решение в слещующем виде: final Pair, Map>> res2 = pairs.stream() .collect( paired( @@ -56,9 +154,17 @@ public void collectKeyValueMap() { ) ); + res1.getKeyById().forEach((s, key) -> { + String k = res2.getA().get(s).getId(); + assertEquals(s, k); + }); + + res1.getValueById().forEach((s, values) -> { + List values2 = res2.getB().get(s); + assertEquals(values.get(0), values2.get(0)); + assertEquals(values.size(), values2.size()); + }); - // TODO tests - throw new UnsupportedOperationException(); } } diff --git a/src/test/java/part3/exercise/lambda/LambdaExercise.java b/src/test/java/part3/exercise/lambda/LambdaExercise.java index 752e1f2..6d4c299 100755 --- a/src/test/java/part3/exercise/lambda/LambdaExercise.java +++ b/src/test/java/part3/exercise/lambda/LambdaExercise.java @@ -15,19 +15,23 @@ public class LambdaExercise { public void supply() { final Person person = new Person("John", "Galt", 30); - final Supplier getPerson = null; // TODO return person from Supplier + final Supplier getPerson = () -> person; assertEquals(person, getPerson.get()); } @Test public void function() { - final Function getPersonName1 = null; // TODO get the name of person using expression lambda + final Function getPersonName1 = person -> person.getFirstName(); // TODO get the name of person using expression lambda - final Function getPersonName2 = null; // TODO get the name of person using method reference + final Function getPersonName2 = Person::getFirstName; // TODO get the name of person using method reference // TODO get the name of person and log it to System.out using statement lambda: {} - final Function getPersonNameAndLogIt = null; + final Function getPersonNameAndLogIt = person -> { + String firstName = person.getFirstName(); + System.out.println(firstName); + return firstName; + }; final Person person = new Person("John", "Galt", 30); @@ -38,19 +42,20 @@ public void function() { @Test public void combineFunctions() { - final Function getPersonName = null; // TODO get the name of person + final Function getPersonName = Person::getFirstName; // TODO get the name of person assertEquals("John", getPersonName.apply(new Person("John", "Galt", 30))); - final Function getStringLength = null; // TODO get string length + final Function getStringLength = s -> s.length(); // TODO get string length assertEquals(Integer.valueOf(3), getStringLength.apply("ABC")); // TODO get person name length using getPersonName and getStringLength without andThen - final Function getPersonNameLength1 = null; + final Function getPersonNameLength1 = + person -> getStringLength.apply(getPersonName.apply(person)); // TODO get person name length using getPersonName and getStringLength with andThen - final Function getPersonNameLength2 = null; + final Function getPersonNameLength2 = getPersonName.andThen(getStringLength); final Person person = new Person("John", "Galt", 30); @@ -69,25 +74,28 @@ private Person createPerson(PersonFactory pf) { // ((T -> R), (R -> boolean)) -> (T -> boolean) private Predicate combine(Function f, Predicate p) { // TODO - throw new UnsupportedOperationException(); + return t -> p.test(f.apply(t)); } @Test public void methodReference() { // TODO use only method reverences here. - final Person person = createPerson(null); // TODO + final Person person = createPerson(Person::new); // TODO assertEquals(new Person("John", "Galt", 66), person); - final Function getPersonName = null; // TODO + final Function getPersonName = Person::getFirstName; // TODO assertEquals("John", getPersonName.apply(person)); - final Predicate isJohnString = null; // TODO using method reference check that "John" equals string parameter + final Predicate isJohnString = this::johnTest; // TODO using method reference check that "John" equals string parameter final Predicate isJohnPerson = combine(getPersonName, isJohnString); assertEquals(true, isJohnPerson.test(person)); } + private boolean johnTest(String name){ + return name.equals("John"); + } } diff --git a/src/test/java/part3/exercise/stream/StreamsExercise.java b/src/test/java/part3/exercise/stream/StreamsExercise.java index 4e2d54b..ed10f4b 100755 --- a/src/test/java/part3/exercise/stream/StreamsExercise.java +++ b/src/test/java/part3/exercise/stream/StreamsExercise.java @@ -3,14 +3,14 @@ import data.Employee; import data.JobHistoryEntry; import data.Person; +import org.apache.commons.lang3.builder.EqualsBuilder; +import org.apache.commons.lang3.builder.HashCodeBuilder; import org.apache.commons.lang3.builder.ToStringBuilder; import org.junit.Test; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.Map; +import java.util.*; +import static java.util.stream.Collectors.*; import static org.junit.Assert.assertEquals; public class StreamsExercise { @@ -19,7 +19,10 @@ public class StreamsExercise { public void getAllJobHistoryEntries() { final List employees = getEmployees(); - final List jobHistoryEntries = null; // TODO + final List jobHistoryEntries = + employees.stream() + .flatMap(employee -> employee.getJobHistory().stream()) + .collect(toList()); // TODO assertEquals(22, jobHistoryEntries.size()); } @@ -29,12 +32,16 @@ public void getSumDuration() { // sum all durations for all persons final List employees = getEmployees(); - final int sumDurations = 0; // TODO + final int sumDurations = + employees.stream() + .flatMap(employee -> employee.getJobHistory().stream()) + .mapToInt(JobHistoryEntry::getDuration) + .sum(); assertEquals(72, sumDurations); } - private static class PersonEmployer{ + private static class PersonEmployer { private final Person person; private final String employer; @@ -64,7 +71,13 @@ public String toString() { public void indexPersonsByEmployer1() { final List employees = getEmployees(); - final Map> index = null; // TODO + final Map> index = + employees.stream() + .flatMap(e -> e.getJobHistory() + .stream() + .map(j -> new PersonEmployer(e.getPerson(), j.getEmployer())) + ) + .collect(groupingBy(PersonEmployer::getEmployer)); assertEquals(11, index.get("epam").size()); } @@ -73,7 +86,18 @@ public void indexPersonsByEmployer1() { public void indexPersonsByEmployer2() { final List employees = getEmployees(); - final Map> index = null; // TODO + final Map> index = + employees.stream() + .flatMap(e -> e.getJobHistory() + .stream() + .map(j -> new PersonEmployer(e.getPerson(), j.getEmployer())) + ) + .collect( + groupingBy( + PersonEmployer::getEmployer, + mapping(PersonEmployer::getPerson, toList()) + ) + ); assertEquals(11, index.get("epam").size()); } @@ -105,8 +129,12 @@ public String toString() { } private PersonDuration sumAllPersonDurations(Employee e) { - // TODO - throw new UnsupportedOperationException(); + final int sum = + e.getJobHistory().stream() + .mapToInt(JobHistoryEntry::getDuration) + .sum(); + + return new PersonDuration(e.getPerson(), sum); } @Test @@ -114,7 +142,14 @@ public void getSumPersonDuration() { // sum all durations for each person final List employees = getEmployees(); - final Map personDuration = null; // TODO use sumAllPersonDurations + final Map personDuration = + employees.stream() + .map(this::sumAllPersonDurations) + .collect(toMap( + PersonDuration::getPerson, + PersonDuration::getDuration, + (u, u2) -> u + )); assertEquals(Integer.valueOf(8), personDuration.get(new Person("John", "Doe", 24))); } @@ -138,15 +173,27 @@ public Map getDurationByPositionIndex() { } private static PersonPositionIndex getPersonPositionIndex(Employee e) { - // TODO - throw new UnsupportedOperationException(); + Map durationByPositionIndex = + e.getJobHistory().stream() + .collect( + toMap( + JobHistoryEntry::getPosition, + JobHistoryEntry::getDuration, + (i1, i2) -> i1 + ) + ); + return new PersonPositionIndex(e.getPerson(), durationByPositionIndex); } @Test public void getSumDurationsForPersonByPosition() { final List employees = getEmployees(); - final List personIndexes = null; // TODO use getPersonPositionIndex + final List personIndexes = + employees.stream() + .map(StreamsExercise::getPersonPositionIndex) + .collect(toList()); + assertEquals(1, personIndexes.get(3).getDurationByPositionIndex().size()); } @@ -173,13 +220,42 @@ public String getPosition() { public int getDuration() { return duration; } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + + if (o == null || getClass() != o.getClass()) return false; + + PersonPositionDuration ppd = (PersonPositionDuration) o; + + return new EqualsBuilder() + .append(person, ppd.getPerson()) + .append(position, ppd.getPosition()) + .isEquals(); + } + + @Override + public int hashCode() { + return new HashCodeBuilder(17, 37) + .append(person) + .append(position) + .toHashCode(); + } } @Test public void getDurationsForEachPersonByPosition() { final List employees = getEmployees(); - final List personPositionDurations = null; // TODO + final List personPositionDurations = + employees.stream() + .flatMap(e -> e.getJobHistory() + .stream() + .map(j -> new PersonPositionDuration(e.getPerson(), j.getPosition(), j.getDuration())) + ) + .distinct() + .collect(toList()); assertEquals(17, personPositionDurations.size()); @@ -190,7 +266,21 @@ public void getCoolestPersonByPosition1() { // Get person with max duration on given position final List employees = getEmployees(); - final Map coolestPersonByPosition = null;// TODO + final Map coolestPersonByPosition = + employees.stream() + .flatMap(e -> e.getJobHistory() + .stream() + .map(j -> new PersonPositionDuration(e.getPerson(), j.getPosition(), j.getDuration())) + ) + .collect( + groupingBy( + PersonPositionDuration::getPosition, + collectingAndThen( + maxBy(Comparator.comparing(PersonPositionDuration::getDuration)), + Optional::get + ) + ) + ); assertEquals(new Person("John", "White", 22), coolestPersonByPosition.get("QA").getPerson()); @@ -201,7 +291,20 @@ public void getCoolestPersonByPosition2() { // Get person with max duration on given position final List employees = getEmployees(); - final Map coolestPersonByPosition = null; // TODO + final Map coolestPersonByPosition = + employees.stream() + .flatMap(e -> e.getJobHistory() + .stream() + .map(j -> new PersonPositionDuration(e.getPerson(), j.getPosition(), j.getDuration())) + ) + .collect( + groupingBy( + PersonPositionDuration::getPosition, + collectingAndThen( + maxBy(Comparator.comparing(PersonPositionDuration::getDuration)), + personPositionDuration -> personPositionDuration.get().getPerson() + )) + ); assertEquals(new Person("John", "White", 22), coolestPersonByPosition.get("QA"));