diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000..9a874b5 Binary files /dev/null and b/.DS_Store differ diff --git a/src/.DS_Store b/src/.DS_Store new file mode 100644 index 0000000..ca5d0e6 Binary files /dev/null and b/src/.DS_Store differ diff --git a/src/test/.DS_Store b/src/test/.DS_Store new file mode 100644 index 0000000..55c1fcb Binary files /dev/null and b/src/test/.DS_Store differ diff --git a/src/test/java/.DS_Store b/src/test/java/.DS_Store new file mode 100644 index 0000000..7004f70 Binary files /dev/null and b/src/test/java/.DS_Store differ diff --git a/src/test/java/part2/.DS_Store b/src/test/java/part2/.DS_Store new file mode 100644 index 0000000..f212fe4 Binary files /dev/null and b/src/test/java/part2/.DS_Store differ diff --git a/src/test/java/part2/exercise/CollectorsExercise1.java b/src/test/java/part2/exercise/CollectorsExercise1.java index 46b6765..ff79169 100755 --- a/src/test/java/part2/exercise/CollectorsExercise1.java +++ b/src/test/java/part2/exercise/CollectorsExercise1.java @@ -6,17 +6,12 @@ import org.junit.Test; import java.util.*; -import java.util.concurrent.ThreadLocalRandom; -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 java.util.stream.Collectors; -import java.util.stream.IntStream; import java.util.stream.Stream; -import static java.util.stream.Collectors.toList; +import static java.util.stream.Collectors.*; public class CollectorsExercise1 { @@ -51,18 +46,46 @@ public int getDuration() { } } + public Stream convert(Employee employee) { + return employee.getJobHistory().stream() + .map(j -> new PersonPositionDuration(employee.getPerson(), j.getPosition(), j.getDuration())); + } + + public Stream convertToSum(final Employee employee) { + return employee.getJobHistory() + .stream() + .collect( + groupingBy( + JobHistoryEntry::getPosition, + collectingAndThen(Collectors.summarizingInt(JobHistoryEntry::getDuration), IntSummaryStatistics::getSum) + )) + .entrySet() + .stream() + .map((k) -> new PersonPositionDuration(employee.getPerson(), k.getKey(), k.getValue().intValue())); + } + // With the longest duration on single job private Map getCoolestByPosition(List employees) { - // First option - // Collectors.maxBy - // Collectors.collectingAndThen - // Collectors.groupingBy - - // Second option - // Collectors.toMap - // iterate twice: stream...collect(...).stream()... - // TODO - throw new UnsupportedOperationException(); + final Map collect = employees + .stream() + .flatMap(this::convert) + .collect(groupingBy(PersonPositionDuration::getPosition, + collectingAndThen(Collectors.maxBy(Comparator.comparingInt(PersonPositionDuration::getDuration)), + e -> e.map(PersonPositionDuration::getPerson).get()))); + + final Map collect1 = employees + .stream() + .flatMap(this::convert) + .collect( + toMap( + PersonPositionDuration::getPosition, + Function.identity(), + BinaryOperator.maxBy(Comparator.comparingInt(PersonPositionDuration::getDuration)) + )) + .entrySet() + .stream() + .collect(toMap(Map.Entry::getKey, e -> e.getValue().getPerson())); + return collect; } @Test @@ -75,8 +98,15 @@ public void getTheCoolestOne2() { // With the longest sum duration on this position // { John Doe, [{dev, google, 4}, {dev, epam, 4}] } предпочтительнее, чем { A B, [{dev, google, 6}, {QA, epam, 100}]} private Map getCoolestByPosition2(List employees) { - // TODO - throw new UnsupportedOperationException(); + return employees + .stream() + .flatMap(this::convertToSum) + .collect(groupingBy + (PersonPositionDuration::getPosition, + collectingAndThen(Collectors.maxBy(Comparator.comparingInt(PersonPositionDuration::getDuration)), + e -> e.map(PersonPositionDuration::getPerson).get() + ) + )); } private List getEmployees() { diff --git a/src/test/java/part2/exercise/CollectorsExercise2.java b/src/test/java/part2/exercise/CollectorsExercise2.java index 00fda00..4ede17c 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.*; @@ -16,14 +13,17 @@ import java.util.stream.IntStream; import java.util.stream.Stream; +import static java.util.stream.Collectors.groupingBy; import static java.util.stream.Collectors.toList; +import static java.util.stream.Collectors.toMap; +import static org.junit.Assert.assertEquals; public class CollectorsExercise2 { private static String generateString() { - final String letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; - final int maxLength = 10; - final int length = ThreadLocalRandom.current().nextInt(maxLength) + 1; + final String letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + final int maxLength = 10; + final int length = ThreadLocalRandom.current().nextInt(maxLength) + 1; return IntStream.range(0, length) .mapToObj(letters::charAt) @@ -31,20 +31,20 @@ private static String generateString() { .collect(Collectors.joining()); } - private static String[] generateStringArray(int length) { + private static String[] generateStringArray(final int length) { return Stream.generate(CollectorsExercise2::generateString) .limit(length) .toArray(String[]::new); } - public static String pickString(String[] array) { + public static String pickString(final String[] array) { return array[ThreadLocalRandom.current().nextInt(array.length)]; } public static class Key { private final String id; - public Key(String id) { + public Key(final String id) { this.id = id; } @@ -72,7 +72,7 @@ public int hashCode() { public static class Value { private final String keyId; - public Value(String keyId) { + public Value(final String keyId) { this.keyId = keyId; } @@ -85,7 +85,7 @@ public static class Pair { private final Key key; private final Value value; - public Pair(Key key, Value value) { + public Pair(final Key key, final Value value) { this.key = key; this.value = value; } @@ -99,7 +99,7 @@ public Value getValue() { } } - public static List generatePairs(int idCount, int length) { + public static List generatePairs(final int idCount, final int length) { final String[] ids = generateStringArray(idCount); return Stream.generate(() -> new Pair(new Key(pickString(ids)), new Value(pickString(ids)))) @@ -112,7 +112,13 @@ private static class SubResult { private final Map> knownKeys; private final Map> valuesWithoutKeys; - public SubResult(Map> subResult, Map> knownKeys, Map> valuesWithoutKeys) { + public SubResult() { + this(new HashMap<>(), new HashMap<>(), new HashMap<>()); + } + + public SubResult(final Map> subResult, + final Map> knownKeys, + final Map> valuesWithoutKeys) { this.subResult = subResult; this.knownKeys = knownKeys; this.valuesWithoutKeys = valuesWithoutKeys; @@ -139,7 +145,8 @@ public MapPair() { this(new HashMap<>(), new HashMap<>()); } - public MapPair(Map keyById, Map> valueById) { + + public MapPair(final Map keyById, final Map> valueById) { this.keyById = keyById; this.valueById = valueById; } @@ -154,7 +161,7 @@ public Map> getValueById() { } private static > - BinaryOperator mapMerger(BinaryOperator mergeFunction) { + BinaryOperator mapMerger(final BinaryOperator mergeFunction) { return (m1, m2) -> { for (Map.Entry e : m2.entrySet()) { m1.merge(e.getKey(), e.getValue(), mergeFunction); @@ -168,32 +175,51 @@ public void collectKeyValueMap() { final List pairs = generatePairs(10, 100); // В два прохода - // final Map keyMap1 = pairs.stream()... + final Map keyMap1 = pairs + .stream() + .map(Pair::getKey) + .collect(toMap(Key::getId, Function.identity(), (a, b) -> a)); - // final Map> valuesMap1 = pairs.stream()... + final Map> valueMap1 = pairs + .stream() + .map(Pair::getValue) + .collect(groupingBy(Value::getKeyId)); // В каждом Map.Entry id ключа должно совпадать с keyId для каждого значения в списке - // final Map> keyValuesMap1 = valueMap1.entrySet().stream()... + final Map> keyValuesMap1 = valueMap1 + .entrySet() + .stream() + .collect(toMap(e -> keyMap1.get(e.getKey()), Map.Entry::getValue)); // В 1 проход в 2 Map с использованием MapPair и mapMerger final MapPair res2 = pairs.stream() .collect(new Collector() { @Override public Supplier supplier() { - // TODO - throw new UnsupportedOperationException(); + return MapPair::new; } @Override public BiConsumer accumulator() { - // TODO add key and value to maps - throw new UnsupportedOperationException(); + return (mp, p) -> { + mp.getKeyById().put(p.getKey().getId(), p.getKey()); + mp.getValueById().computeIfAbsent(p.getValue().getKeyId(), v -> new ArrayList<>()).add(p.getValue()); + }; } @Override public BinaryOperator combiner() { - // TODO use mapMerger - throw new UnsupportedOperationException(); + return (p1, p2) -> { + final BinaryOperator> mapBinaryOperator = mapMerger((a, b) -> a); + final BinaryOperator>> mapBinaryOperator1 = mapMerger((a, b) -> { + a.addAll(b); + return a; + }); + final Map apply = mapBinaryOperator.apply(p1.getKeyById(), p2.getKeyById()); + final Map> apply1 = mapBinaryOperator1.apply(p1.getValueById(), p2.getValueById()); + return new MapPair(apply, apply1); + + }; } @Override @@ -209,49 +235,14 @@ public Set characteristics() { } }); - final Map keyMap2 = res2.getKeyById(); + final Map keyMap2 = res2.getKeyById(); final Map> valuesMap2 = res2.getValueById(); - // final Map> keyValuesMap2 = valueMap2.entrySet().stream()... - - // Получение результата сразу: - - final SubResult res3 = pairs.stream() - .collect(new Collector() { - @Override - public Supplier supplier() { - // TODO - throw new UnsupportedOperationException(); - } - - @Override - public BiConsumer accumulator() { - // TODO add key to map, then check value.keyId and add it to one of maps - throw new UnsupportedOperationException(); - } - - @Override - public BinaryOperator combiner() { - // TODO use mapMerger, then check all valuesWithoutKeys - throw new UnsupportedOperationException(); - } - - @Override - public Function finisher() { - // TODO use mapMerger, then check all valuesWithoutKeys - throw new UnsupportedOperationException(); - } - - @Override - public Set characteristics() { - return Collections.unmodifiableSet(EnumSet.of( - Characteristics.UNORDERED)); - } - }); - - final Map> keyValuesMap3 = res3.getSubResult(); + final Map> keyValuesMap2 = valuesMap2 + .entrySet() + .stream() + .collect(toMap(e -> keyMap2.get(e.getKey()), Map.Entry::getValue)); - // compare results + assertEquals(keyValuesMap1, keyValuesMap2); } - } diff --git a/src/test/java/part3/.DS_Store b/src/test/java/part3/.DS_Store new file mode 100644 index 0000000..cc09190 Binary files /dev/null and b/src/test/java/part3/.DS_Store differ diff --git a/src/test/java/part3/exercise/CollectorCombination.java b/src/test/java/part3/exercise/CollectorCombination.java index 15a42d5..1265969 100755 --- a/src/test/java/part3/exercise/CollectorCombination.java +++ b/src/test/java/part3/exercise/CollectorCombination.java @@ -5,12 +5,18 @@ import part2.exercise.CollectorsExercise2.Key; import part2.exercise.CollectorsExercise2.Value; +import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Set; +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 { @@ -34,8 +40,38 @@ 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 (p, e) -> { + c1.accumulator().accept(p.getA(), e); + c2.accumulator().accept(p.getB(), e); + }; + } + + @Override + public BinaryOperator> combiner() { + return (l, r) -> new Pair<>(c1.combiner().apply(l.getA(), r.getA()), + c2.combiner().apply(l.getB(), r.getB())); + } + + @Override + public Function, Pair> finisher() { + return (p) -> new Pair<>(c1.finisher().apply(p.getA()), c2.finisher().apply(p.getB())); + } + + @Override + public Set characteristics() { + final Set tmp = new HashSet<>(c1.characteristics()); + tmp.retainAll(c2.characteristics()); + return tmp; + } + }; } @Test @@ -56,9 +92,19 @@ public void collectKeyValueMap() { ) ); + final Map keyMap1 = pairs + .stream() + .map(CollectorsExercise2.Pair::getKey) + .collect(toMap(Key::getId, Function.identity(), (a, b) -> a)); + + final Map> valueMap1 = pairs + .stream() + .map(CollectorsExercise2.Pair::getValue) + .collect(groupingBy(Value::getKeyId)); + + assertEquals(res2.getA(), keyMap1); + assertEquals(res2.getB(), valueMap1); - // 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..e81c770 100755 --- a/src/test/java/part3/exercise/lambda/LambdaExercise.java +++ b/src/test/java/part3/exercise/lambda/LambdaExercise.java @@ -15,19 +15,22 @@ 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 = () -> new Person("John", "Galt", 30); assertEquals(person, getPerson.get()); } @Test public void function() { - final Function getPersonName1 = null; // 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 + 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 = person -> { + final String firstName = person.getFirstName(); + System.out.println(firstName); + return firstName; + }; final Person person = new Person("John", "Galt", 30); @@ -38,19 +41,17 @@ public void function() { @Test public void combineFunctions() { - final Function getPersonName = null; // 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 + 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); @@ -68,22 +69,21 @@ private Person createPerson(PersonFactory pf) { // ((T -> R), (R -> boolean)) -> (T -> boolean) private Predicate combine(Function f, Predicate p) { - // TODO - throw new UnsupportedOperationException(); + //comopose look + return e -> p.test(f.apply(e)); } @Test public void methodReference() { - // TODO use only method reverences here. - final Person person = createPerson(null); // TODO + final Person person = createPerson(Person::new); assertEquals(new Person("John", "Galt", 66), person); - final Function getPersonName = null; // TODO + final Function getPersonName = Person::getFirstName; assertEquals("John", getPersonName.apply(person)); - final Predicate isJohnString = null; // TODO using method reference check that "John" equals string parameter + final Predicate isJohnString = "John"::equals; final Predicate isJohnPerson = combine(getPersonName, isJohnString); diff --git a/src/test/java/part3/exercise/stream/StreamsExercise.java b/src/test/java/part3/exercise/stream/StreamsExercise.java index 4e2d54b..554175a 100755 --- a/src/test/java/part3/exercise/stream/StreamsExercise.java +++ b/src/test/java/part3/exercise/stream/StreamsExercise.java @@ -6,11 +6,13 @@ 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 java.util.Comparator.comparingInt; +import static java.util.stream.Collectors.*; import static org.junit.Assert.assertEquals; public class StreamsExercise { @@ -19,26 +21,32 @@ public class StreamsExercise { public void getAllJobHistoryEntries() { final List employees = getEmployees(); - final List jobHistoryEntries = null; // TODO + final List jobHistoryEntries = employees + .stream() + .flatMap(e -> e.getJobHistory().stream()) + .collect(Collectors.toList()); assertEquals(22, jobHistoryEntries.size()); } @Test public void getSumDuration() { - // sum all durations for all persons final List employees = getEmployees(); - final int sumDurations = 0; // TODO + final int sumDurations = employees + .stream() + .flatMap(e -> e.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; - public PersonEmployer(Person person, String employer) { + public PersonEmployer(final Person person, final String employer) { this.person = person; this.employer = employer; } @@ -64,7 +72,12 @@ 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(Collectors.groupingBy(PersonEmployer::getEmployer)); assertEquals(11, index.get("epam").size()); } @@ -73,7 +86,12 @@ public void indexPersonsByEmployer1() { public void indexPersonsByEmployer2() { final List employees = getEmployees(); - final Map> index = null; // TODO + 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()); } @@ -104,9 +122,8 @@ public String toString() { } } - private PersonDuration sumAllPersonDurations(Employee e) { - // TODO - throw new UnsupportedOperationException(); + private PersonDuration sumAllPersonDurations(final Employee e) { + return new PersonDuration(e.getPerson(), e.getJobHistory().stream().mapToInt(JobHistoryEntry::getDuration).sum()); } @Test @@ -114,7 +131,11 @@ 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(Collectors.toMap(PersonDuration::getPerson, PersonDuration::getDuration)); + assertEquals(Integer.valueOf(8), personDuration.get(new Person("John", "Doe", 24))); } @@ -138,15 +159,23 @@ public Map getDurationByPositionIndex() { } private static PersonPositionIndex getPersonPositionIndex(Employee e) { - // TODO - throw new UnsupportedOperationException(); + return new PersonPositionIndex(e.getPerson(), + e.getJobHistory() + .stream() + .collect(Collectors + .groupingBy( + JobHistoryEntry::getPosition, + collectingAndThen(summingInt(JobHistoryEntry::getDuration), Integer::intValue)))); } @Test public void getSumDurationsForPersonByPosition() { final List employees = getEmployees(); - final List personIndexes = null; // TODO use getPersonPositionIndex + final List personIndexes = employees + .stream() + .map(StreamsExercise::getPersonPositionIndex) + .collect(Collectors.toList()); assertEquals(1, personIndexes.get(3).getDurationByPositionIndex().size()); } @@ -179,8 +208,14 @@ public int getDuration() { public void getDurationsForEachPersonByPosition() { final List employees = getEmployees(); - final List personPositionDurations = null; // TODO - + final List personPositionDurations = employees + .stream() + .map(StreamsExercise::getPersonPositionIndex) + .flatMap(e -> e.getDurationByPositionIndex() + .entrySet() + .stream() + .map(j -> new PersonPositionDuration(e.getPerson(), j.getKey(), j.getValue()))) + .collect(toList()); assertEquals(17, personPositionDurations.size()); } @@ -190,7 +225,16 @@ 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() + .map(StreamsExercise::getPersonPositionIndex) + .flatMap(e -> e.getDurationByPositionIndex() + .entrySet() + .stream() + .map(j -> new PersonPositionDuration(e.getPerson(), j.getKey(), j.getValue()))) + .collect(toMap(PersonPositionDuration::getPosition, + Function.identity(), + BinaryOperator.maxBy(comparingInt(PersonPositionDuration::getDuration)))); assertEquals(new Person("John", "White", 22), coolestPersonByPosition.get("QA").getPerson()); @@ -201,7 +245,21 @@ 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() + .map(StreamsExercise::getPersonPositionIndex) + .flatMap(e -> e.getDurationByPositionIndex() + .entrySet() + .stream() + .map(j -> new PersonPositionDuration(e.getPerson(), j.getKey(), j.getValue()))) + .collect( + groupingBy( + PersonPositionDuration::getPosition, + collectingAndThen( + maxBy(comparingInt(PersonPositionDuration::getDuration)), + l -> l.get().getPerson() + ) + )); assertEquals(new Person("John", "White", 22), coolestPersonByPosition.get("QA"));