From 31221f8d1dbb221511234a8d06a4f10c2ec19d94 Mon Sep 17 00:00:00 2001 From: Nikita Golubev Date: Tue, 11 Jul 2017 18:50:08 +0300 Subject: [PATCH 1/2] Generator --- src/main/java/data/Generator.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/java/data/Generator.java b/src/main/java/data/Generator.java index cbd46ea..2584f86 100644 --- a/src/main/java/data/Generator.java +++ b/src/main/java/data/Generator.java @@ -60,7 +60,8 @@ public static Employee generateEmployee() { } public static List generateEmployeeList() { - // TODO - throw new UnsupportedOperationException(); + return Stream.generate(Generator::generateEmployee) + .limit(15) + .collect(toList()); } } From 7e9c98aa5c9a20b13877327e017cd033484cc980 Mon Sep 17 00:00:00 2001 From: Nikita Golubev Date: Thu, 13 Jul 2017 16:00:32 +0300 Subject: [PATCH 2/2] part2 --- .../part2/exercise/CollectorsExercise1.java | 90 ++++++++- .../part2/exercise/CollectorsExercise2.java | 176 +++++++++--------- 2 files changed, 177 insertions(+), 89 deletions(-) diff --git a/src/test/java/part2/exercise/CollectorsExercise1.java b/src/test/java/part2/exercise/CollectorsExercise1.java index 46b6765..d179c8b 100755 --- a/src/test/java/part2/exercise/CollectorsExercise1.java +++ b/src/test/java/part2/exercise/CollectorsExercise1.java @@ -23,7 +23,6 @@ public class CollectorsExercise1 { @Test public void getTheCoolestOne() { final Map coolestByPosition = getCoolestByPosition(getEmployees()); - coolestByPosition.forEach((position, person) -> System.out.println(position + " -> " + person)); } @@ -61,8 +60,78 @@ private Map getCoolestByPosition(List employees) { // Second option // Collectors.toMap // iterate twice: stream...collect(...).stream()... - // TODO - throw new UnsupportedOperationException(); + final Map result; + + employees.stream() + .flatMap(CollectorsExercise1::employeeInfo) + .collect(Collectors.groupingBy(PersonPositionDuration::getPosition, Collectors.collectingAndThen( + Collectors.maxBy( + Comparator.comparingInt(PersonPositionDuration::getDuration)), + info -> info.get().getPerson()))); + employees.stream() + .flatMap(CollectorsExercise1::employeeInfo) + .collect(new Collector, Map>() { + @Override + public Supplier> supplier() { + return HashMap::new; + } + + @Override + public BiConsumer, PersonPositionDuration> accumulator() { + return (map, info) -> map.merge( + info.getPosition(), + info, + (ppd1,ppd2) -> ppd2.getDuration() > ppd1.getDuration() ? ppd2 : ppd1); + } + + @Override + public BinaryOperator> combiner() { + return (map1,map2) -> { + for (PersonPositionDuration info : map2.values()){ + PersonPositionDuration mapInfo = map1.get(info.getPosition()); + if (mapInfo == null || info.getDuration() > mapInfo.getDuration()){ + map1.put(info.getPosition(),info); + } + } + return map1; + }; + } + + @Override + public Function, Map> finisher() { + return mapInfo -> mapInfo + .entrySet() + .stream() + .map(Map.Entry::getValue) + .collect(Collectors.toMap( + PersonPositionDuration::getPosition, + PersonPositionDuration::getPerson)); + } + + @Override + public Set characteristics() { + return Collections.emptySet(); + } + }); + + result = getCoolestByPositionFromStream(employees.stream().flatMap(CollectorsExercise1::employeeInfo)); + return result; + } + + private static Stream employeeInfo(Employee employee) { + return employee.getJobHistory().stream() + .map(entry -> new PersonPositionDuration(employee.getPerson(), + entry.getPosition(), + entry.getDuration())); + } + + private static Map getCoolestByPositionFromStream(Stream upstream){ + return upstream + .collect(Collectors.toMap(PersonPositionDuration::getPosition,Function.identity(), + (ppd1,ppd2) -> ppd2.getDuration() > ppd1.getDuration() ? ppd2 : ppd1)) + .entrySet() + .stream() + .collect(Collectors.toMap(Map.Entry::getKey,entry -> entry.getValue().getPerson())); } @Test @@ -75,8 +144,19 @@ 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 getCoolestByPositionFromStream(employees.stream() + .flatMap(CollectorsExercise1::employeeInfoDuration)); + } + + private static Stream employeeInfoDuration(Employee employee) { + return employeeInfo(employee) + .collect(Collectors.groupingBy(PersonPositionDuration::getPosition)) + .entrySet() + .stream() + .map(entry -> new PersonPositionDuration( + employee.getPerson(), + entry.getKey(), + entry.getValue().stream().mapToInt(PersonPositionDuration::getDuration).sum())); } private List getEmployees() { diff --git a/src/test/java/part2/exercise/CollectorsExercise2.java b/src/test/java/part2/exercise/CollectorsExercise2.java index 00fda00..c55ad24 100755 --- a/src/test/java/part2/exercise/CollectorsExercise2.java +++ b/src/test/java/part2/exercise/CollectorsExercise2.java @@ -16,10 +16,12 @@ import java.util.stream.IntStream; import java.util.stream.Stream; -import static java.util.stream.Collectors.toList; +import static java.util.stream.Collectors.*; +import static org.junit.Assert.assertEquals; public class CollectorsExercise2 { + private static String generateString() { final String letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; final int maxLength = 10; @@ -131,15 +133,15 @@ public Map> getKnownKeys() { } } - private static class MapPair { + public static class MapPair { private final Map keyById; - private final Map> valueById; + private final Map> valueById; public MapPair() { this(new HashMap<>(), new HashMap<>()); } - public MapPair(Map keyById, Map> valueById) { + public MapPair(Map keyById, Map> valueById) { this.keyById = keyById; this.valueById = valueById; } @@ -148,17 +150,67 @@ public Map getKeyById() { return keyById; } - public Map> getValueById() { + public Map> getValueById() { return valueById; } } - private static > + static class MapPairCollector implements Collector { + + @Override + public Supplier supplier() { + return MapPair::new; + } + + @Override + public BiConsumer accumulator() { + return (MapPair mapPair, Pair pair) -> { + mapPair.getKeyById().put(pair.getKey().getId(), pair.getKey()); + mapPair.getValueById() + .merge( + pair.getValue().getKeyId(), + new HashSet<>(Collections.singletonList(pair.getValue())), + (values, values2) -> { + values.addAll(values2); + return values; + }); + }; + } + + @Override + public BinaryOperator combiner() { + return (mapPair, mapPair2) -> { + BinaryOperator> keyMerger = mapMerger((key, key2) -> key); + Map keyMap = keyMerger.apply(mapPair.getKeyById(), mapPair2.getKeyById()); + + BinaryOperator>> valueMerger = mapMerger((values, values2) -> { + values.addAll(values2); + return values; + }); + Map> valueMap = valueMerger.apply(mapPair.getValueById(), mapPair2.getValueById()); + + return new MapPair(keyMap, valueMap); + }; + } + + @Override + public Function finisher() { + return Function.identity(); + } + + @Override + public Set characteristics() { + return Collections.unmodifiableSet(EnumSet.of( + Characteristics.UNORDERED, + Characteristics.IDENTITY_FINISH)); + } + } + + public static > BinaryOperator mapMerger(BinaryOperator mergeFunction) { return (m1, m2) -> { - for (Map.Entry e : m2.entrySet()) { + for (Map.Entry e : m2.entrySet()) m1.merge(e.getKey(), e.getValue(), mergeFunction); - } return m1; }; } @@ -168,90 +220,46 @@ public void collectKeyValueMap() { final List pairs = generatePairs(10, 100); // В два прохода - // final Map keyMap1 = pairs.stream()... - - // final Map> valuesMap1 = pairs.stream()... + final Map keyMap1 = pairs.stream() + .collect( + toMap( + p -> p.getKey().getId(), + Pair::getKey, + (key, key2) -> key) + ); + + final Map> valuesMap1 = pairs.stream() + .collect( + groupingBy( + p -> p.getValue().getKeyId(), + mapping(Pair::getValue, toSet()) + ) + ); // В каждом Map.Entry id ключа должно совпадать с keyId для каждого значения в списке - // final Map> keyValuesMap1 = valueMap1.entrySet().stream()... + final Map> keyValuesMap1 = valuesMap1.entrySet().stream() + .filter(entry -> keyMap1.containsKey(entry.getKey())) + .collect( + toMap( + entry -> keyMap1.get(entry.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(); - } - - @Override - public BiConsumer accumulator() { - // TODO add key and value to maps - throw new UnsupportedOperationException(); - } - - @Override - public BinaryOperator combiner() { - // TODO use mapMerger - throw new UnsupportedOperationException(); - } - - @Override - public Function finisher() { - return Function.identity(); - } - - @Override - public Set characteristics() { - return Collections.unmodifiableSet(EnumSet.of( - Characteristics.UNORDERED, - Characteristics.IDENTITY_FINISH)); - } - }); - + .collect(new MapPairCollector()); 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> valuesMap2 = res2.getValueById(); - final Map> keyValuesMap3 = res3.getSubResult(); + final Map> keyValuesMap2 = valuesMap2.entrySet().stream() + .filter(entry -> keyMap2.containsKey(entry.getKey())) + .collect( + toMap( + entry -> keyMap2.get(entry.getKey()), + Map.Entry::getValue) + ); - // compare results + assertEquals(keyValuesMap1, keyValuesMap2); } }