From 6f37f7635b6df79ee3c0ae8ca4e800490d274483 Mon Sep 17 00:00:00 2001 From: Michael-Georg Date: Tue, 11 Apr 2017 23:27:24 +0300 Subject: [PATCH 1/8] part 1 hw and CollectorsExercise1 --- src/main/java/data/Generator.java | 7 +- .../java/part1/exercise/StreamsExercise1.java | 62 +++++--- .../java/part1/exercise/StreamsExercise2.java | 95 ++++++++++-- .../part2/exercise/CollectorsExercise1.java | 140 ++++++++++++++++-- 4 files changed, 252 insertions(+), 52 deletions(-) diff --git a/src/main/java/data/Generator.java b/src/main/java/data/Generator.java index cbd46ea..8cc7467 100644 --- a/src/main/java/data/Generator.java +++ b/src/main/java/data/Generator.java @@ -60,7 +60,10 @@ public static Employee generateEmployee() { } public static List generateEmployeeList() { - // TODO - throw new UnsupportedOperationException(); + int maxLength = 10; + final int length = ThreadLocalRandom.current().nextInt(maxLength) + 1; + return Stream.generate(Generator::generateEmployee) + .limit(length) + .collect(toList()); } } diff --git a/src/test/java/part1/exercise/StreamsExercise1.java b/src/test/java/part1/exercise/StreamsExercise1.java index 02dd2da..6fbeff0 100755 --- a/src/test/java/part1/exercise/StreamsExercise1.java +++ b/src/test/java/part1/exercise/StreamsExercise1.java @@ -5,16 +5,12 @@ import data.Person; import org.junit.Test; -import java.util.*; -import java.util.concurrent.ThreadLocalRandom; -import java.util.stream.Collectors; -import java.util.stream.IntStream; -import java.util.stream.Stream; +import java.util.ArrayList; +import java.util.List; import static data.Generator.generateEmployeeList; -import static java.util.stream.Collectors.groupingBy; -import static java.util.stream.Collectors.mapping; import static java.util.stream.Collectors.toList; +import static org.junit.Assert.assertEquals; public class StreamsExercise1 { // https://youtu.be/kxgo7Y4cdA8 Сергей Куксенко и Алексей Шипилёв — Через тернии к лямбдам, часть 1 @@ -25,20 +21,48 @@ public class StreamsExercise1 { @Test public void getAllEpamEmployees() { - List epamEmployees = null;// TODO all persons with experience in epam - throw new UnsupportedOperationException(); + final List employees = generateEmployeeList(); + + List expected = new ArrayList<>(); + + for (Employee e : employees) { + for (JobHistoryEntry j : e.getJobHistory()) { + if (j.getEmployer().equals("epam")) { + expected.add(e.getPerson()); + break; + } + } + } + List actual = employees.stream() + .filter(e -> e.getJobHistory().stream() + .map(JobHistoryEntry::getEmployer).anyMatch(employer -> employer.equals("epam"))) + .map(Employee::getPerson) + .collect(toList()); + + assertEquals(expected, actual); } @Test public void getEmployeesStartedFromEpam() { - List epamEmployees = null;// TODO all persons with first experience in epam - throw new UnsupportedOperationException(); + final List employees = generateEmployeeList(); + + List expected = new ArrayList<>(); + + for (Employee e : employees) { + if (e.getJobHistory().get(0).equals("epam")) + expected.add(e.getPerson()); + } + List actual = employees.stream() + .filter(e -> e.getJobHistory().get(0).equals("epam")) + .map(Employee::getPerson) + .collect(toList()); + + assertEquals(expected, actual); } @Test public void sumEpamDurations() { final List employees = generateEmployeeList(); - int expected = 0; for (Employee e : employees) { @@ -48,12 +72,12 @@ public void sumEpamDurations() { } } } - - // TODO - throw new UnsupportedOperationException(); - - // int result = ??? - // assertEquals(expected, result); + int result = employees.stream() + .map(Employee::getJobHistory) + .flatMap(e -> e.stream() + .filter(h -> h.getEmployer().equals("epam"))) + .mapToInt(JobHistoryEntry::getDuration) + .sum(); + assertEquals(expected, result); } - } diff --git a/src/test/java/part1/exercise/StreamsExercise2.java b/src/test/java/part1/exercise/StreamsExercise2.java index 5be9d38..5d5c6a0 100755 --- a/src/test/java/part1/exercise/StreamsExercise2.java +++ b/src/test/java/part1/exercise/StreamsExercise2.java @@ -5,15 +5,11 @@ import data.Person; import org.junit.Test; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.stream.Stream; +import java.util.*; -import static data.Generator.generateEmployeeList; import static java.util.stream.Collectors.*; -import static org.junit.Assert.assertEquals; +import static org.hamcrest.core.IsEqual.equalTo; +import static org.junit.Assert.assertThat; public class StreamsExercise2 { // https://youtu.be/kxgo7Y4cdA8 Сергей Куксенко и Алексей Шипилёв — Через тернии к лямбдам, часть 1 @@ -22,25 +18,94 @@ public class StreamsExercise2 { // https://youtu.be/O8oN4KSZEXE Сергей Куксенко — Stream API, часть 1 // https://youtu.be/i0Jr2l3jrDA Сергей Куксенко — Stream API, часть 2 - // TODO class PersonEmployerPair + // TODO class PersonEmployerDuration + private static class PersonEmployerDuration + { + private Person person; + private String employer; + private Integer duration; + + PersonEmployerDuration(Person p, String e) { + this(p,e,0); + } + + PersonEmployerDuration(Person p, String e, Integer d) { + employer = e; + person = p; + duration = d; + } + + Person getPerson() { + return person; + } + + String getEmployer() { + return employer; + } + + int getDuration() { + return duration; + } + } @Test public void employersStuffLists() { - Map> employersStuffLists = null;// TODO - throw new UnsupportedOperationException(); + Map> employersStuffLists = getEmployees().stream() + .flatMap(e -> e.getJobHistory() + .stream() + .map(j -> new PersonEmployerDuration( + e.getPerson(), + j.getEmployer()))) + .collect(groupingBy( + PersonEmployerDuration::getEmployer, + mapping(PersonEmployerDuration::getPerson, toList()))); + + assertThat(employersStuffLists.get("Microsoft"), + equalTo(Collections.singletonList(new Person("John", "White", 25)))); } @Test public void indexByFirstEmployer() { - Map> employeesIndex = null;// TODO - throw new UnsupportedOperationException(); + Map> employeesIndex = getEmployees().stream() + .map(e -> new PersonEmployerDuration( + e.getPerson(), + e.getJobHistory().get(0).getEmployer())) + .collect(groupingBy(PersonEmployerDuration::getEmployer, + mapping(PersonEmployerDuration::getPerson, toList()))); + + assertThat(employeesIndex.get("abc"), equalTo(null)); + assertThat(employeesIndex.get("yandex"), equalTo(Arrays.asList( + new Person("John", "Doe", 21), + new Person("John", "Doe", 24), + new Person("Bob", "Doe", 27), + new Person("John", "Doe", 30)))); + } + + private static Map jobHistory(List jobHistory){ + return jobHistory.stream() + .collect(groupingBy( + JobHistoryEntry::getEmployer, + summingInt(JobHistoryEntry::getDuration))); } @Test public void greatestExperiencePerEmployer() { - Map employeesIndex = null;// TODO + Map employeesIndex = getEmployees().stream() + .flatMap(e -> jobHistory(e.getJobHistory()) + .entrySet().stream() + .map(j -> new PersonEmployerDuration( + e.getPerson(), + j.getKey(), + j.getValue())) + ) + .collect(groupingBy( + PersonEmployerDuration::getEmployer, + collectingAndThen(maxBy(Comparator.comparingInt(PersonEmployerDuration::getDuration)), + p->p.get().getPerson())) + ); + - assertEquals(new Person("John", "White", 28), employeesIndex.get("epam")); + assertThat(new Person("John", "White", 28), equalTo(employeesIndex.get("epam"))); } @@ -80,7 +145,7 @@ private List getEmployees() { new Employee( new Person("John", "White", 25), Collections.singletonList( - new JobHistoryEntry(6, "QA", "epam") + new JobHistoryEntry(6, "QA", "Microsoft") )), new Employee( new Person("John", "Galt", 26), diff --git a/src/test/java/part2/exercise/CollectorsExercise1.java b/src/test/java/part2/exercise/CollectorsExercise1.java index 46b6765..f49aa27 100755 --- a/src/test/java/part2/exercise/CollectorsExercise1.java +++ b/src/test/java/part2/exercise/CollectorsExercise1.java @@ -6,25 +6,28 @@ 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.function.*; 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.Comparator.comparing; +import static java.util.stream.Collectors.*; +import static org.hamcrest.core.Is.is; +import static org.hamcrest.core.IsEqual.equalTo; +import static org.junit.Assert.assertThat; public class CollectorsExercise1 { @Test public void getTheCoolestOne() { - final Map coolestByPosition = getCoolestByPosition(getEmployees()); + final Map coolestByPositionVersion1 = getCoolestByPositionVersion1(getEmployees()); + final Map coolestByPositionVersion2 = getCoolestByPositionVersion2(getEmployees()); + final Map coolestByPositionVersion3 = getCoolestByPositionVersion3(getEmployees()); - coolestByPosition.forEach((position, person) -> System.out.println(position + " -> " + person)); + assertThat(coolestByPositionVersion1.get("BA"), equalTo(coolestByPositionVersion2.get("BA"))); + assertThat(coolestByPositionVersion1.get("BA"), equalTo(coolestByPositionVersion3.get("BA"))); + assertThat(coolestByPositionVersion1.get("dev"), equalTo(coolestByPositionVersion2.get("dev"))); + assertThat(coolestByPositionVersion1.get("dev"), equalTo(coolestByPositionVersion3.get("dev"))); } private static class PersonPositionDuration { @@ -52,7 +55,7 @@ public int getDuration() { } // With the longest duration on single job - private Map getCoolestByPosition(List employees) { + private Map getCoolestByPositionVersion1(List employees) { // First option // Collectors.maxBy // Collectors.collectingAndThen @@ -61,22 +64,125 @@ private Map getCoolestByPosition(List employees) { // Second option // Collectors.toMap // iterate twice: stream...collect(...).stream()... - // TODO - throw new UnsupportedOperationException(); + return employees.stream() + .flatMap(e -> e.getJobHistory() + .stream() + .map(j -> new PersonPositionDuration( + e.getPerson(), + j.getPosition(), + j.getDuration())) + ) + .collect(groupingBy( + PersonPositionDuration::getPosition, + collectingAndThen(maxBy( + comparing(PersonPositionDuration::getDuration)), + p -> p.get().getPerson()))); } + private Map getCoolestByPositionVersion2(List employees) { + return employees.stream() + .flatMap(e -> e.getJobHistory() + .stream() + .map(j -> new PersonPositionDuration( + e.getPerson(), + j.getPosition(), + j.getDuration()))) + .collect(Collectors.toMap( + PersonPositionDuration::getPosition, + Function.identity(), + (d1, d2) -> d1.getDuration() > d2.getDuration() ? d1 : d2)) + .entrySet().stream() + .collect(toMap( + Map.Entry::getKey, + e -> e.getValue().getPerson())); + } + + private Map getCoolestByPositionVersion3(List employees) { + return employees.stream() + .flatMap(e -> e.getJobHistory() + .stream() + .map(j -> new PersonPositionDuration( + e.getPerson(), + j.getPosition(), + j.getDuration()))) + .collect(new Collector, Map>() { + + @Override + public Supplier> supplier() { + return HashMap::new; + } + + @Override + public BiConsumer, PersonPositionDuration> accumulator() { + return (map, p) -> map.merge( + p.getPosition(), + p, + (p1, p2) -> p1.getDuration() > p2.getDuration() ? p1 : p2); + } + + @Override + public BinaryOperator> combiner() { + return (map1, map2) -> { + map1.putAll( + map2.entrySet().stream() + .filter(el -> !map1.containsKey(el.getKey()) + || map1.get(el.getKey()).getDuration() < el.getValue().getDuration()) + .collect(toMap( + Map.Entry::getKey, + Map.Entry::getValue)) + ); + return map1; + }; + } + + @Override + public Function, Map> finisher() { + return map -> map.entrySet().stream() + .collect(toMap( + Map.Entry::getKey, + e -> e.getValue().getPerson())); + } + + @Override + public Set characteristics() { + return Collections.EMPTY_SET; + } + }); + } + + @Test public void getTheCoolestOne2() { final Map coolestByPosition = getCoolestByPosition2(getEmployees()); - coolestByPosition.forEach((position, person) -> System.out.println(position + " -> " + person)); + assertThat(coolestByPosition.size(), is(3)); + assertThat(coolestByPosition.get("BA"), equalTo(new Person("John", "White", 28))); + assertThat(coolestByPosition.get("QA"), equalTo(new Person("John", "Doe", 24))); + } + + private static Map durationOnPositions(List jobHistory) { + return jobHistory.stream() + .collect(groupingBy( + JobHistoryEntry::getPosition, + summingInt(JobHistoryEntry::getDuration))); } // 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(employee -> durationOnPositions(employee.getJobHistory()) + .entrySet().stream() + .map(position -> new PersonPositionDuration( + employee.getPerson(), + position.getKey(), + position.getValue())) + ) + .collect(groupingBy( + PersonPositionDuration::getPosition, + collectingAndThen( + maxBy(comparing(PersonPositionDuration::getDuration)), + p -> p.get().getPerson()))); } private List getEmployees() { @@ -109,7 +215,9 @@ private List getEmployees() { new Person("John", "Doe", 24), Arrays.asList( new JobHistoryEntry(4, "QA", "yandex"), + new JobHistoryEntry(2, "QA", "epam"), new JobHistoryEntry(2, "BA", "epam"), + new JobHistoryEntry(1, "QA", "abc"), new JobHistoryEntry(2, "dev", "abc") )), new Employee( From 009e1851b9c4e74d93dc38a5dff9a4a8763d2519 Mon Sep 17 00:00:00 2001 From: Michael-Georg Date: Tue, 11 Apr 2017 23:55:30 +0300 Subject: [PATCH 2/8] LambdaExercise --- .../part3/exercise/lambda/LambdaExercise.java | 29 ++++++++++--------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/src/test/java/part3/exercise/lambda/LambdaExercise.java b/src/test/java/part3/exercise/lambda/LambdaExercise.java index 752e1f2..190dc5b 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; // 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 + 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 name = person.getFirstName(); + System.out.println(name); + return name; + }; final Person person = new Person("John", "Galt", 30); @@ -38,19 +42,19 @@ 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 = String::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 = 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 +72,21 @@ 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 = "John"::equals; // TODO using method reference check that "John" equals string parameter final Predicate isJohnPerson = combine(getPersonName, isJohnString); From 3c4547f3fd33cca67c34b59b0f44cd57a7f5274d Mon Sep 17 00:00:00 2001 From: Michael-Georg Date: Thu, 13 Apr 2017 15:09:46 +0300 Subject: [PATCH 3/8] CollectorsExercise2 start --- .../part2/exercise/CollectorsExercise2.java | 44 ++++++++++++++----- 1 file changed, 32 insertions(+), 12 deletions(-) diff --git a/src/test/java/part2/exercise/CollectorsExercise2.java b/src/test/java/part2/exercise/CollectorsExercise2.java index 00fda00..e0f534e 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,7 +13,9 @@ 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; public class CollectorsExercise2 { @@ -168,32 +167,53 @@ 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(), (k1, k2) -> k1)); - // 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.getValue()), + 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 (map, pair) -> { + map.getKeyById().put(pair.getKey().getId(), pair.getKey()); + map.getValueById().computeIfAbsent( + pair.getValue().getKeyId(), + e -> map.getValueById() + .put(pair.getValue().getKeyId() + , new ArrayList<>())).add(pair.getValue()); + }; } @Override public BinaryOperator combiner() { - // TODO use mapMerger - throw new UnsupportedOperationException(); + return (map1, map2) -> { + BinaryOperator> mapBinaryOperator = mapMerger((o, o2) -> o2); + BinaryOperator>> mapBinaryOperatorToo = mapMerger((list, list2) -> { + list.addAll(list2); + return list; + }); + + mapBinaryOperator.apply(map1.getKeyById(), map2.getKeyById()); + mapBinaryOperatorToo.apply(map1.getValueById(), map2.getValueById()); + return map1; + }; } @Override From 29f328d1e1fedbbb8984c78904cf1a97cd49107d Mon Sep 17 00:00:00 2001 From: Michael-Georg Date: Thu, 13 Apr 2017 18:35:02 +0300 Subject: [PATCH 4/8] CollectorsExercise2 fix + test --- .../part2/exercise/CollectorsExercise2.java | 150 +++++++++++------- 1 file changed, 96 insertions(+), 54 deletions(-) diff --git a/src/test/java/part2/exercise/CollectorsExercise2.java b/src/test/java/part2/exercise/CollectorsExercise2.java index e0f534e..4bd40d0 100755 --- a/src/test/java/part2/exercise/CollectorsExercise2.java +++ b/src/test/java/part2/exercise/CollectorsExercise2.java @@ -16,6 +16,8 @@ import static java.util.stream.Collectors.groupingBy; import static java.util.stream.Collectors.toList; import static java.util.stream.Collectors.toMap; +import static org.hamcrest.core.IsEqual.equalTo; +import static org.junit.Assert.assertThat; public class CollectorsExercise2 { @@ -78,6 +80,28 @@ public Value(String keyId) { public String getKeyId() { return keyId; } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + Value value = (Value) o; + + return keyId != null ? keyId.equals(value.keyId) : value.keyId == null; + } + + @Override + public int hashCode() { + return keyId != null ? keyId.hashCode() : 0; + } + + @Override + public String toString() { + return "Value{" + + "keyId='" + keyId + '\'' + + '}'; + } } public static class Pair { @@ -167,19 +191,22 @@ public void collectKeyValueMap() { final List pairs = generatePairs(10, 100); // В два прохода - final Map keyMap1 = pairs.stream() - .map(Pair::getKey) - .collect(toMap(Key::getId, Function.identity(), (k1, k2) -> k1)); + final Map keyMap1 = pairs.stream() + .map(Pair::getKey) + .collect(toMap(Key::getId, Function.identity(), (k1, k2) -> k2)); - final Map> valueMap1 = pairs.stream() - .map(Pair::getValue) + final Map> valueMap1 = pairs.stream() + .map(Pair::getValue) .collect(groupingBy(Value::getKeyId)); // В каждом Map.Entry id ключа должно совпадать с keyId для каждого значения в списке - final Map> keyValuesMap1 = valueMap1.entrySet().stream() - .collect(toMap(e->keyMap1.get(e.getValue()), - Map.Entry::getValue)); - + final Map> keyValuesMap1 = valueMap1.entrySet().stream() + .collect(toMap(e -> keyMap1.get(e.getKey()), + Map.Entry::getValue, + (values, values2) -> { + values.addAll(values2); + return values; + })); // В 1 проход в 2 Map с использованием MapPair и mapMerger final MapPair res2 = pairs.stream() @@ -192,27 +219,28 @@ public Supplier supplier() { @Override public BiConsumer accumulator() { return (map, pair) -> { - map.getKeyById().put(pair.getKey().getId(), pair.getKey()); - map.getValueById().computeIfAbsent( - pair.getValue().getKeyId(), - e -> map.getValueById() - .put(pair.getValue().getKeyId() - , new ArrayList<>())).add(pair.getValue()); + map.getKeyById().merge(pair.getKey().getId(), pair.getKey(), (key, key2) -> key); + map.getValueById() + .computeIfAbsent(pair.getValue().getKeyId(), (t) -> new ArrayList<>()) + .add(pair.getValue()); }; } @Override public BinaryOperator combiner() { return (map1, map2) -> { - BinaryOperator> mapBinaryOperator = mapMerger((o, o2) -> o2); + BinaryOperator> mapBinaryOperator = mapMerger((o, o2) -> o); BinaryOperator>> mapBinaryOperatorToo = mapMerger((list, list2) -> { list.addAll(list2); return list; }); - mapBinaryOperator.apply(map1.getKeyById(), map2.getKeyById()); - mapBinaryOperatorToo.apply(map1.getValueById(), map2.getValueById()); - return map1; + Map keyMap = + mapBinaryOperator.apply(map1.getKeyById(), map2.getKeyById()); + Map> valueMap = + mapBinaryOperatorToo.apply(map1.getValueById(), map2.getValueById()); + + return new MapPair(keyMap, valueMap); }; } @@ -232,44 +260,58 @@ public Set characteristics() { final Map keyMap2 = res2.getKeyById(); final Map> valuesMap2 = res2.getValueById(); - // final Map> keyValuesMap2 = valueMap2.entrySet().stream()... + final Map> keyValuesMap2 = valuesMap2 + .entrySet().stream() + .collect(toMap(e->keyMap2.get(e.getKey()), + Map.Entry::getValue, + (values, values2) -> { + values.addAll(values2); + return values; + })); + assertThat(keyMap1, equalTo(keyMap2)); + assertThat(keyValuesMap1.keySet(), equalTo(keyValuesMap2.keySet())); + + Key randomKey = keyMap1.entrySet().stream() + .map(Map.Entry::getValue) + .findAny() + .orElse(null); + assertThat(keyValuesMap1.get(randomKey), equalTo(keyValuesMap2.get(randomKey))); // Получение результата сразу: - 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 SubResult res3 = pairs.stream() +// .collect(new Collector() { +// @Override +// public Supplier supplier() { +// return SubResult::new; +// } +// +// @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(); // compare results } From 68100a6cf4f033880c4ddd2547bd800980c18597 Mon Sep 17 00:00:00 2001 From: Michael-Georg Date: Thu, 13 Apr 2017 18:48:58 +0300 Subject: [PATCH 5/8] Fixed remarks --- src/test/java/part1/exercise/StreamsExercise1.java | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/test/java/part1/exercise/StreamsExercise1.java b/src/test/java/part1/exercise/StreamsExercise1.java index 6fbeff0..86abcbf 100755 --- a/src/test/java/part1/exercise/StreamsExercise1.java +++ b/src/test/java/part1/exercise/StreamsExercise1.java @@ -35,7 +35,8 @@ public void getAllEpamEmployees() { } List actual = employees.stream() .filter(e -> e.getJobHistory().stream() - .map(JobHistoryEntry::getEmployer).anyMatch(employer -> employer.equals("epam"))) + .map(JobHistoryEntry::getEmployer) + .anyMatch("epam"::equals)) .map(Employee::getPerson) .collect(toList()); @@ -49,17 +50,24 @@ public void getEmployeesStartedFromEpam() { List expected = new ArrayList<>(); for (Employee e : employees) { - if (e.getJobHistory().get(0).equals("epam")) + if (isFirstEmployerEpam(e)) expected.add(e.getPerson()); } List actual = employees.stream() - .filter(e -> e.getJobHistory().get(0).equals("epam")) + .filter(StreamsExercise1::isFirstEmployerEpam) .map(Employee::getPerson) .collect(toList()); assertEquals(expected, actual); } + private static boolean isFirstEmployerEpam(Employee e) { + return e.getJobHistory() + .stream() + .limit(1) + .anyMatch("epam"::equals); + } + @Test public void sumEpamDurations() { final List employees = generateEmployeeList(); From 5f8147d1d858989fc6f78740180bb78989f89f61 Mon Sep 17 00:00:00 2001 From: Michael-Georg Date: Thu, 13 Apr 2017 21:48:42 +0300 Subject: [PATCH 6/8] part 3 StreamExercise --- .../exercise/stream/StreamsExercise.java | 77 +++++++++++++++---- 1 file changed, 62 insertions(+), 15 deletions(-) diff --git a/src/test/java/part3/exercise/stream/StreamsExercise.java b/src/test/java/part3/exercise/stream/StreamsExercise.java index 4e2d54b..37911e8 100755 --- a/src/test/java/part3/exercise/stream/StreamsExercise.java +++ b/src/test/java/part3/exercise/stream/StreamsExercise.java @@ -10,16 +10,25 @@ import java.util.Collections; import java.util.List; import java.util.Map; +import java.util.function.BinaryOperator; +import java.util.function.Function; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import static java.util.Comparator.comparingInt; +import static java.util.stream.Collectors.*; import static org.junit.Assert.assertEquals; +@SuppressWarnings("WeakerAccess") public class StreamsExercise { @Test public void getAllJobHistoryEntries() { final List employees = getEmployees(); - final List jobHistoryEntries = null; // TODO + final List jobHistoryEntries = employees.stream() + .flatMap(e -> e.getJobHistory().stream()) + .collect(toList()); assertEquals(22, jobHistoryEntries.size()); } @@ -29,12 +38,15 @@ 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; @@ -64,16 +76,24 @@ public String toString() { public void indexPersonsByEmployer1() { final List employees = getEmployees(); - final Map> index = null; // TODO - + final Map> index = getPersonEmployerStream(employees) + .collect(groupingBy(PersonEmployer::getEmployer)); assertEquals(11, index.get("epam").size()); } + private static Stream getPersonEmployerStream(List employees) { + return employees.stream() + .flatMap(e -> e.getJobHistory().stream() + .map(t -> new PersonEmployer(e.getPerson(), t.getEmployer()))); + } + @Test public void indexPersonsByEmployer2() { final List employees = getEmployees(); - final Map> index = null; // TODO + final Map> index = getPersonEmployerStream(employees) + .collect(groupingBy(PersonEmployer::getEmployer, + mapping(PersonEmployer::getPerson, toList()))); assertEquals(11, index.get("epam").size()); } @@ -105,8 +125,11 @@ public String toString() { } private PersonDuration sumAllPersonDurations(Employee e) { - // TODO - throw new UnsupportedOperationException(); + int duration = e.getJobHistory() + .stream() + .mapToInt(JobHistoryEntry::getDuration) + .sum(); + return new PersonDuration(e.getPerson(), duration); } @Test @@ -114,7 +137,10 @@ 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)); assertEquals(Integer.valueOf(8), personDuration.get(new Person("John", "Doe", 24))); } @@ -138,15 +164,19 @@ public Map getDurationByPositionIndex() { } private static PersonPositionIndex getPersonPositionIndex(Employee e) { - // TODO - throw new UnsupportedOperationException(); + Map collect = e.getJobHistory().stream() + .collect(groupingBy(JobHistoryEntry::getPosition, + summingInt(JobHistoryEntry::getDuration))); + return new PersonPositionIndex(e.getPerson(), collect); } @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()); } @@ -179,18 +209,31 @@ public int getDuration() { public void getDurationsForEachPersonByPosition() { final List employees = getEmployees(); - final List personPositionDurations = null; // TODO + final List personPositionDurations = getPersonPositionDurationStream(employees) + .collect(toList()); assertEquals(17, personPositionDurations.size()); } + private Stream getPersonPositionDurationStream(List employees) { + return employees.stream() + .map(StreamsExercise::getPersonPositionIndex) + .flatMap(e -> e.getDurationByPositionIndex().entrySet().stream() + .map(p -> new PersonPositionDuration(e.getPerson(), p.getKey(), p.getValue()))); + } + @Test public void getCoolestPersonByPosition1() { // Get person with max duration on given position final List employees = getEmployees(); - final Map coolestPersonByPosition = null;// TODO + final Map coolestPersonByPosition = + getPersonPositionDurationStream(employees) + .collect(toMap( + PersonPositionDuration::getPosition, + Function.identity(), + BinaryOperator.maxBy(comparingInt(PersonPositionDuration::getDuration)))); assertEquals(new Person("John", "White", 22), coolestPersonByPosition.get("QA").getPerson()); @@ -201,7 +244,11 @@ public void getCoolestPersonByPosition2() { // Get person with max duration on given position final List employees = getEmployees(); - final Map coolestPersonByPosition = null; // TODO + final Map coolestPersonByPosition = + getPersonPositionDurationStream(employees) + .collect(groupingBy(PersonPositionDuration::getPosition, + collectingAndThen(Collectors.maxBy(comparingInt(PersonPositionDuration::getDuration)), + o -> o.get().getPerson()))); assertEquals(new Person("John", "White", 22), coolestPersonByPosition.get("QA")); From d6ca595feb32236533e44506304cc9230a54013b Mon Sep 17 00:00:00 2001 From: Michael-Georg Date: Thu, 13 Apr 2017 23:24:43 +0300 Subject: [PATCH 7/8] part 3 CollectorCombination --- .../part2/exercise/CollectorsExercise2.java | 88 ++++++------------- .../part3/exercise/CollectorCombination.java | 63 ++++++++++--- 2 files changed, 78 insertions(+), 73 deletions(-) diff --git a/src/test/java/part2/exercise/CollectorsExercise2.java b/src/test/java/part2/exercise/CollectorsExercise2.java index 4bd40d0..21e8bf9 100755 --- a/src/test/java/part2/exercise/CollectorsExercise2.java +++ b/src/test/java/part2/exercise/CollectorsExercise2.java @@ -19,6 +19,7 @@ import static org.hamcrest.core.IsEqual.equalTo; import static org.junit.Assert.assertThat; +@SuppressWarnings("WeakerAccess") public class CollectorsExercise2 { private static String generateString() { @@ -154,7 +155,7 @@ public Map> getKnownKeys() { } } - private static class MapPair { + public static class MapPair { private final Map keyById; private final Map> valueById; @@ -209,7 +210,31 @@ public void collectKeyValueMap() { })); // В 1 проход в 2 Map с использованием MapPair и mapMerger - final MapPair res2 = pairs.stream() + final MapPair res2 = getMapPair(pairs); + + final Map keyMap2 = res2.getKeyById(); + final Map> valuesMap2 = res2.getValueById(); + + final Map> keyValuesMap2 = valuesMap2 + .entrySet().stream() + .collect(toMap(e->keyMap2.get(e.getKey()), + Map.Entry::getValue, + (values, values2) -> { + values.addAll(values2); + return values; + })); + assertThat(keyMap1, equalTo(keyMap2)); + assertThat(keyValuesMap1.keySet(), equalTo(keyValuesMap2.keySet())); + + Key randomKey = keyMap1.entrySet().stream() + .map(Map.Entry::getValue) + .findAny() + .orElse(null); + assertThat(keyValuesMap1.get(randomKey), equalTo(keyValuesMap2.get(randomKey))); + } + + public static MapPair getMapPair(List pairs) { + return pairs.stream() .collect(new Collector() { @Override public Supplier supplier() { @@ -256,64 +281,5 @@ public Set characteristics() { Characteristics.IDENTITY_FINISH)); } }); - - final Map keyMap2 = res2.getKeyById(); - final Map> valuesMap2 = res2.getValueById(); - - final Map> keyValuesMap2 = valuesMap2 - .entrySet().stream() - .collect(toMap(e->keyMap2.get(e.getKey()), - Map.Entry::getValue, - (values, values2) -> { - values.addAll(values2); - return values; - })); - assertThat(keyMap1, equalTo(keyMap2)); - assertThat(keyValuesMap1.keySet(), equalTo(keyValuesMap2.keySet())); - - Key randomKey = keyMap1.entrySet().stream() - .map(Map.Entry::getValue) - .findAny() - .orElse(null); - assertThat(keyValuesMap1.get(randomKey), equalTo(keyValuesMap2.get(randomKey))); - - // Получение результата сразу: - -// final SubResult res3 = pairs.stream() -// .collect(new Collector() { -// @Override -// public Supplier supplier() { -// return SubResult::new; -// } -// -// @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(); - - // compare results } - } diff --git a/src/test/java/part3/exercise/CollectorCombination.java b/src/test/java/part3/exercise/CollectorCombination.java index 15a42d5..b34d379 100755 --- a/src/test/java/part3/exercise/CollectorCombination.java +++ b/src/test/java/part3/exercise/CollectorCombination.java @@ -5,12 +5,19 @@ import part2.exercise.CollectorsExercise2.Key; import part2.exercise.CollectorsExercise2.Value; +import java.util.Collections; 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.hamcrest.core.IsEqual.equalTo; +import static org.junit.Assert.assertThat; public class CollectorCombination { @@ -34,19 +41,46 @@ 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 (pair, t) -> { + c1.accumulator().accept(pair.getA(), t); + c2.accumulator().accept(pair.getB(), t); + }; + } + + @Override + public BinaryOperator> combiner() { + return (m1M2Pair, m1M2Pair2) -> { + M1 m1 = c1.combiner().apply(m1M2Pair.getA(), m1M2Pair2.getA()); + M2 m2 = c2.combiner().apply(m1M2Pair.getB(), m1M2Pair2.getB()); + return new Pair<>(m1, m2); + }; + } + + @Override + public Function, Pair> finisher() { + return m1M2Pair -> new Pair<>( + c1.finisher().apply(m1M2Pair.getA()), + c2.finisher().apply(m1M2Pair.getB())); + } + + @Override + public Set characteristics() { + return Collections.emptySet(); + } + }; } @Test public void collectKeyValueMap() { - // TODO see CollectorsExercise1::collectKeyValueMap - // В 1 проход в 2 Map с использованием MapPair и mapMerger - // final MapPair res2 = pairs.stream() - // .collect(new Collector() { - - // Перепишите решение в слещующем виде: - final List pairs = CollectorsExercise2.generatePairs(10, 100); + final List pairs = CollectorsExercise2.generatePairs(8, 100); final Pair, Map>> res2 = pairs.stream() .collect( @@ -56,9 +90,14 @@ public void collectKeyValueMap() { ) ); + CollectorsExercise2.MapPair mapPair = CollectorsExercise2.getMapPair(pairs); + assertThat(res2.getA(), equalTo(mapPair.getKeyById())); - // TODO tests - throw new UnsupportedOperationException(); + String randomKey = mapPair.getKeyById().entrySet().stream() + .map(Map.Entry::getKey) + .findAny() + .orElse(null); + assertThat(mapPair.getValueById().get(randomKey), equalTo(res2.getB().get(randomKey))); } -} +} \ No newline at end of file From bb5a87e40886c3cc468e7f16348f1855216f64e4 Mon Sep 17 00:00:00 2001 From: Michael-Georg Date: Fri, 14 Apr 2017 16:23:08 +0300 Subject: [PATCH 8/8] deleted BinaryOperator in toMap realisation --- .../java/part2/exercise/CollectorsExercise2.java | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/src/test/java/part2/exercise/CollectorsExercise2.java b/src/test/java/part2/exercise/CollectorsExercise2.java index 21e8bf9..4536da8 100755 --- a/src/test/java/part2/exercise/CollectorsExercise2.java +++ b/src/test/java/part2/exercise/CollectorsExercise2.java @@ -203,11 +203,7 @@ public void collectKeyValueMap() { // В каждом Map.Entry id ключа должно совпадать с keyId для каждого значения в списке final Map> keyValuesMap1 = valueMap1.entrySet().stream() .collect(toMap(e -> keyMap1.get(e.getKey()), - Map.Entry::getValue, - (values, values2) -> { - values.addAll(values2); - return values; - })); + Map.Entry::getValue)); // В 1 проход в 2 Map с использованием MapPair и mapMerger final MapPair res2 = getMapPair(pairs); @@ -218,11 +214,8 @@ public void collectKeyValueMap() { final Map> keyValuesMap2 = valuesMap2 .entrySet().stream() .collect(toMap(e->keyMap2.get(e.getKey()), - Map.Entry::getValue, - (values, values2) -> { - values.addAll(values2); - return values; - })); + Map.Entry::getValue)); + assertThat(keyMap1, equalTo(keyMap2)); assertThat(keyValuesMap1.keySet(), equalTo(keyValuesMap2.keySet()));