diff --git a/src/test/java/part2/exercise/CollectorsExercise2.java b/src/test/java/part2/exercise/CollectorsExercise2.java index 00fda00..0e1962a 100755 --- a/src/test/java/part2/exercise/CollectorsExercise2.java +++ b/src/test/java/part2/exercise/CollectorsExercise2.java @@ -131,7 +131,7 @@ public Map> getKnownKeys() { } } - private static class MapPair { + public static class MapPair { private final Map keyById; private final Map> valueById; @@ -139,7 +139,7 @@ public MapPair() { this(new HashMap<>(), new HashMap<>()); } - public MapPair(Map keyById, Map> valueById) { + MapPair(Map keyById, Map> valueById) { this.keyById = keyById; this.valueById = valueById; } @@ -151,9 +151,21 @@ public Map getKeyById() { public Map> getValueById() { return valueById; } + + public void put(Pair p) { + keyById.put(p.getKey().getId(), p.getKey()); + final ArrayList value = new ArrayList<>(); + value.add(p.getValue()); + valueById.merge(p.getValue().getKeyId(), + value, + (l1, l2) -> { + l1.addAll(l2); + return l1; + }); + } } - 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..dace2e7 100755 --- a/src/test/java/part3/exercise/CollectorCombination.java +++ b/src/test/java/part3/exercise/CollectorCombination.java @@ -5,12 +5,15 @@ import part2.exercise.CollectorsExercise2.Key; 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 org.junit.Assert.assertEquals; public class CollectorCombination { @@ -30,35 +33,132 @@ public A getA() { public B getB() { return b; } + + @Override + public String toString() { + return String.format("Pair<%s & %s>", a, b); + } } 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 (pair, t) -> { + c1.accumulator().accept(pair.getA(), t); + c2.accumulator().accept(pair.getB(), t); + }; + } + + @Override + public BinaryOperator> combiner() { + return (p1, p2) -> new Pair<> ( + c1.combiner().apply(p1.getA(), p2.getA()), + c2.combiner().apply(p1.getB(), p2.getB())); + } + + @Override + public Function, Pair> finisher() { + return p -> new Pair<> ( + c1.finisher().apply(p.getA()), + c2.finisher().apply(p.getB())); + } + + @Override + public Set characteristics() { + Set set = new HashSet<>(); + set.addAll(c1.characteristics()); + set.addAll(c2.characteristics()); + return set; + } + }; } @Test public void collectKeyValueMap() { + final List pairs = CollectorsExercise2.generatePairs(10, 100); + // TODO see CollectorsExercise1::collectKeyValueMap // В 1 проход в 2 Map с использованием MapPair и mapMerger - // final MapPair res2 = pairs.stream() - // .collect(new Collector() { + final Map> res1 = pairs.stream() + .collect(collectingAndThen( + new Collector() { + @Override + public Supplier supplier() { + // TODO + return CollectorsExercise2.MapPair::new; + } - // Перепишите решение в слещующем виде: - final List pairs = CollectorsExercise2.generatePairs(10, 100); + @Override + public BiConsumer accumulator() { + // TODO + return CollectorsExercise2.MapPair::put; + } + + @Override + public BinaryOperator combiner() { + // TODO + return (mapPair, mapPair2) -> { + BinaryOperator> keyMerger = CollectorsExercise2.mapMerger((v1, v2) -> v1); + keyMerger.apply(mapPair.getKeyById(), mapPair2.getKeyById()); + BinaryOperator>> valueMerger = + CollectorsExercise2.mapMerger((v1, v2) -> { + v1.addAll(v2); + return v1; + }); + valueMerger.apply(mapPair.getValueById(), mapPair2.getValueById()); + return mapPair; + }; + } + + @Override + public Function finisher() { + return Function.identity(); + } + + @Override + public Set characteristics() { + return Collections.unmodifiableSet(EnumSet.of( + Characteristics.UNORDERED, + Characteristics.IDENTITY_FINISH)); + } + }, + (CollectorsExercise2.MapPair mmp) -> mmp.getKeyById().entrySet().stream() + .map(kp -> new AbstractMap.SimpleEntry<>(kp.getValue(), mmp.getValueById().get(kp.getKey()))) + .collect(toMap( + Map.Entry::getKey, + Map.Entry::getValue + )) + ) + ); - final Pair, Map>> res2 = pairs.stream() + // Перепишите решение в слещующем виде: + final Map> res2 = pairs.stream() .collect( - paired( - mapping(CollectorsExercise2.Pair::getKey, toMap(Key::getId, Function.identity(), (x, y) -> x)), - mapping(CollectorsExercise2.Pair::getValue, groupingBy(Value::getKeyId)) + collectingAndThen( + paired( + mapping(CollectorsExercise2.Pair::getKey, + toMap(Key::getId, Function.identity(), (x, y) -> x)), + mapping(CollectorsExercise2.Pair::getValue, + groupingBy(Value::getKeyId)) + ), + mmp -> mmp.getA().entrySet().stream() + .map(kp -> new AbstractMap.SimpleEntry<>(kp.getValue(), mmp.getB().get(kp.getKey()))) + .collect(toMap( + Map.Entry::getKey, + Map.Entry::getValue + )) ) ); - // TODO tests - throw new UnsupportedOperationException(); + assertEquals(res1, res2); } - } diff --git a/src/test/java/part3/exercise/lambda/LambdaExercise.java b/src/test/java/part3/exercise/lambda/LambdaExercise.java index 752e1f2..85f9e35 100755 --- a/src/test/java/part3/exercise/lambda/LambdaExercise.java +++ b/src/test/java/part3/exercise/lambda/LambdaExercise.java @@ -15,19 +15,25 @@ 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; // TODO return person from Supplier assertEquals(person, getPerson.get()); } @Test public void function() { - final Function getPersonName1 = null; // TODO get the name of person using expression lambda + // TODO get the name of person using expression lambda + final Function getPersonName1 = + p -> p.getFirstName(); - final Function getPersonName2 = null; // TODO get the name of person using method reference + // TODO get the name of person using method reference + final Function getPersonName2 = Person::getFirstName; // TODO get the name of person and log it to System.out using statement lambda: {} - final Function getPersonNameAndLogIt = null; + final Function getPersonNameAndLogIt = p -> { + System.out.println(p.getFirstName()); + return p.getFirstName(); + }; final Person person = new Person("John", "Galt", 30); @@ -38,19 +44,20 @@ public void function() { @Test public void combineFunctions() { - final Function getPersonName = null; // TODO get the name of person + // TODO get the name of person + final Function getPersonName = Person::getFirstName; assertEquals("John", getPersonName.apply(new Person("John", "Galt", 30))); - - final Function getStringLength = null; // TODO get string length + // TODO get string length + final Function getStringLength = 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 = p -> getStringLength.apply(getPersonName.apply(p)); // 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 +76,29 @@ private Person createPerson(PersonFactory pf) { // ((T -> R), (R -> boolean)) -> (T -> boolean) private Predicate combine(Function f, Predicate p) { // TODO - throw new UnsupportedOperationException(); + return v -> p.test(f.apply(v)); } @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 + // TODO using method reference check that "John" equals string parameter + final Predicate isJohnString = LambdaExercise::isJohn; final Predicate isJohnPerson = combine(getPersonName, isJohnString); assertEquals(true, isJohnPerson.test(person)); } + private static boolean isJohn(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..5fdf087 100755 --- a/src/test/java/part3/exercise/stream/StreamsExercise.java +++ b/src/test/java/part3/exercise/stream/StreamsExercise.java @@ -6,10 +6,10 @@ 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 java.util.function.BinaryOperator; +import java.util.function.Function; +import java.util.stream.Collectors; import static org.junit.Assert.assertEquals; @@ -19,7 +19,10 @@ public class StreamsExercise { public void getAllJobHistoryEntries() { final List employees = getEmployees(); - final List jobHistoryEntries = null; // TODO + // TODO + final List jobHistoryEntries = employees.stream() + .flatMap(e -> e.getJobHistory().stream()) + .collect(Collectors.toList()); assertEquals(22, jobHistoryEntries.size()); } @@ -28,8 +31,11 @@ public void getAllJobHistoryEntries() { public void getSumDuration() { // sum all durations for all persons final List employees = getEmployees(); - - final int sumDurations = 0; // TODO + // TODO + final int sumDurations = employees.stream() + .flatMap(e -> e.getJobHistory().stream()) + .mapToInt(JobHistoryEntry::getDuration) + .sum(); assertEquals(72, sumDurations); } @@ -64,7 +70,11 @@ public String toString() { public void indexPersonsByEmployer1() { final List employees = getEmployees(); - final Map> index = null; // TODO + // TODO + final Map> index = employees.stream() + .flatMap(e -> e.getJobHistory().stream() + .map(j -> new PersonEmployer(e.getPerson(), j.getEmployer()))) + .collect(Collectors.groupingBy(PersonEmployer::getEmployer)); assertEquals(11, index.get("epam").size()); } @@ -73,7 +83,22 @@ public void indexPersonsByEmployer1() { public void indexPersonsByEmployer2() { final List employees = getEmployees(); - final Map> index = null; // TODO + // TODO + final Map> index = employees.stream() + .flatMap(e -> e.getJobHistory().stream() + .map(j -> new PersonEmployer(e.getPerson(), j.getEmployer()))) + .collect(Collectors.toMap( + PersonEmployer::getEmployer, + pe -> { + final ArrayList persons = new ArrayList<>(); + persons.add(pe.getPerson()); + return persons; + }, + (p1, p2) -> { + p1.addAll(p2); + return p1; + } + )); assertEquals(11, index.get("epam").size()); } @@ -106,7 +131,10 @@ public String toString() { private PersonDuration sumAllPersonDurations(Employee e) { // TODO - throw new UnsupportedOperationException(); + return new PersonDuration(e.getPerson(), + e.getJobHistory().stream() + .mapToInt(JobHistoryEntry::getDuration) + .sum()); } @Test @@ -114,7 +142,11 @@ public void getSumPersonDuration() { // sum all durations for each person final List employees = getEmployees(); - final Map personDuration = null; // TODO use sumAllPersonDurations + // TODO use sumAllPersonDurations + final Map personDuration = employees.stream() + .map(this::sumAllPersonDurations) + .collect(Collectors.toMap(PersonDuration::getPerson, + PersonDuration::getDuration)); assertEquals(Integer.valueOf(8), personDuration.get(new Person("John", "Doe", 24))); } @@ -139,14 +171,22 @@ public Map getDurationByPositionIndex() { private static PersonPositionIndex getPersonPositionIndex(Employee e) { // TODO - throw new UnsupportedOperationException(); + return new PersonPositionIndex(e.getPerson(), e.getJobHistory().stream() + .collect(Collectors.toMap( + JobHistoryEntry::getPosition, + JobHistoryEntry::getDuration, + Integer::sum + ))); } @Test public void getSumDurationsForPersonByPosition() { final List employees = getEmployees(); - final List personIndexes = null; // TODO use getPersonPositionIndex + // TODO use getPersonPositionIndex + final List personIndexes = employees.stream() + .map(StreamsExercise::getPersonPositionIndex) + .collect(Collectors.toList()); assertEquals(1, personIndexes.get(3).getDurationByPositionIndex().size()); } @@ -178,9 +218,19 @@ public int getDuration() { @Test public void getDurationsForEachPersonByPosition() { final List employees = getEmployees(); - - final List personPositionDurations = null; // TODO - + // TODO + final List personPositionDurations = employees.stream() + .flatMap(e -> e.getJobHistory().stream() + .map(j -> new PersonPositionDuration(e.getPerson(), j.getPosition(), j.getDuration())) + .collect(Collectors.toMap( + PersonPositionDuration::getPosition, + Function.identity(), + (PersonPositionDuration ppd1, PersonPositionDuration ppd2) -> + new PersonPositionDuration(ppd1.getPerson(), + ppd1.getPosition(), + ppd1.getDuration() + ppd2.getDuration()) + )).entrySet().stream().map(Map.Entry::getValue)) + .collect(Collectors.toList()); assertEquals(17, personPositionDurations.size()); } @@ -190,7 +240,17 @@ public void getCoolestPersonByPosition1() { // Get person with max duration on given position final List employees = getEmployees(); - final Map coolestPersonByPosition = null;// TODO + // TODO + final Map coolestPersonByPosition = employees.stream() + .flatMap(e -> e.getJobHistory().stream() + .map(j -> new PersonPositionDuration(e.getPerson(), j.getPosition(), j.getDuration()))) + .collect(Collectors.groupingBy( + PersonPositionDuration::getPosition, + Collectors.collectingAndThen( + Collectors.maxBy(Comparator.comparingInt(PersonPositionDuration::getDuration)), + Optional::get + ) + )); assertEquals(new Person("John", "White", 22), coolestPersonByPosition.get("QA").getPerson()); @@ -200,9 +260,16 @@ public void getCoolestPersonByPosition1() { public void getCoolestPersonByPosition2() { // Get person with max duration on given position final List employees = getEmployees(); - - final Map coolestPersonByPosition = null; // TODO - + // TODO + final Map coolestPersonByPosition = employees.stream() + .flatMap(e -> e.getJobHistory().stream() + .map(j -> new PersonPositionDuration(e.getPerson(), j.getPosition(), j.getDuration()))) + .collect(Collectors.toMap( + PersonPositionDuration::getPosition, + Function.identity(), + BinaryOperator.maxBy(Comparator.comparingInt(PersonPositionDuration::getDuration)) + )).entrySet().stream() + .collect(Collectors.toMap(Map.Entry::getKey, e -> e.getValue().getPerson())); assertEquals(new Person("John", "White", 22), coolestPersonByPosition.get("QA")); }