Good afternoon, dear Russian-speaking developers. There is a code that needs to be debugged in a lambda expression. The question has already been asked on an English-language resource , but I did not wait for an exhaustive answer. Is that a comment where it is proposed first aggregation and then assembly into a collection, where I did not understand which particular collector the commentator had in mind. In general, having this method here:

public Map<Job, Map<Sheet, Collection<JobTransform>>> createPartitioning() { Map<Job, Map<Sheet, Collection<JobTransform>>> partitioning = new HashMap<>(); for (Sheet sheet : content) { Map<Job, Collection<JobTransform>> currentMap = sheet.createPartitioning(); for (Map.Entry<Job, Collection<JobTransform>> entry : currentMap.entrySet()) { partitioning .computeIfAbsent(entry.getKey(), key -> new HashMap<>()) .computeIfAbsent(sheet, key -> new LinkedList<>()) .addAll(entry.getValue()); } } return partitioning; } 

I would like to convert it to a lambda expression. All I managed to find out was:

 content.stream().flatMap(sheet -> sheet.createPartitioning().entrySet().stream()).co‌​llect() ... 

But how exactly to write the code inside collect() I, alas, can’t think at all. I will be glad of any help and forgive my not quite clear Russian! For a long time I live abroad and there is not enough practice in the “Russian language in programming”.

  • You have quite a good Russian or use a good translator. - Vladimir Glinskikh

1 answer 1

I will give an example on a simplified conversion (Map<Integer, Map<String, Object>> на Map<String, Map<Integer, Object>>):

 Map<Integer, Map<String, Object>> map2 = map1.entrySet().stream() .flatMap(e1 -> e1.getValue().entrySet() .stream() .map(e2 -> Arrays.asList(e2.getKey(), e1.getKey(), e2.getValue()))) .collect(HashMap::new, (m, l) -> m.put((Integer) l.get(0), Stream.concat(Stream.of(l.subList(1, 3)), m.computeIfAbsent((Integer) l.get(0), HashMap::new) .entrySet() .stream() .map(e -> Arrays.asList(e.getKey(), e.getValue()))) .collect(Collectors.toMap(l1 -> (String) l1.get(0), l1 -> l1 .get(1)))), (m1, m2) -> m2.forEach((k, v) -> m1.put(k, Stream.concat(m1.computeIfAbsent(k, HashMap::new) .entrySet() .stream(), v.entrySet().stream()) .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue))))); 

In its pure form, it will look like this, not very readable, but on lambdas and one line.

However, you can use any class instead of Arrays.asList , also select some operations into separate methods and use method-reference, which improves readability, but also increases the amount of code. Whether you need such a decision depends on you. In my opinion, the decision on cycles is much more obvious.