2

Given the nested HashMap HashMap<Integer,HashMap<Integer,BigDecimal>> is it possible to set to zero inner HashMap values with parallel streams with acceptable side-effects and respecting non-interference rules?

For example,given HashMap:

HashMap<Integer,HashMap<Integer,BigDecimal>> myMap = null;

is the final forEach in:

myMap.entrySet().parallelStream().forEach(e -> {
            e.getValue().entrySet().parallelStream().forEach(e1 -> {
                e1.setValue(new BigDecimal(0));
                });
        });

acceptable side-effects and respecting non-interference rules?

Stefan Zobel
  • 3,182
  • 7
  • 28
  • 38
  • 1
    I have voted to close this question because it is unclear what you are asking. Please see: https://stackoverflow.com/help/how-to-ask and edit the question accordingly. – jrook Oct 25 '18 at 14:47
  • 2
    Check answers on this question: https://stackoverflow.com/questions/32837415/non-interference-exact-meaning-in-java-8-streams – ernest_k Oct 25 '18 at 14:50
  • Basically I asked if the code respects patterns reported in Java Stream documentation expecially when it comes to non-interference and side-effects rules. – giuseppe maugeri Oct 25 '18 at 14:51
  • That may work due to the way the `setValue` method of `HashMap`’s entries have been implemented, at least, when you can guaranty that no hash map instance appears more than once in the outer map’s values. However, how about `myMap.values().forEach(m -> m.replaceAll((k,v) -> BigDecimal.ZERO));`? How much faster does it run, compared to your parallel operation? – Holger Oct 25 '18 at 17:01

1 Answers1

0

... is it possible to set to zero inner HashMap values with parallel streams...

It seems it works, however HashMap is not the thread-safe implementation so I discourage you from using this way.

... with acceptable side-effects and respecting non-interference rules?

Your usage of Stream::forhas side-effects since it changes the source of the Stream. I recommend you to use Stream::map and collecting the structure back to Map afterward using one parrallelStream:

Map<Integer, Map<Integer,BigDecimal>> myMap2 = myMap.entrySet().parallelStream()
    .map(e -> new AbstractMap.SimpleEntry<>(
        e.getKey(), 
        e.getValue().entrySet().stream()
                               .collect(Collectors.toMap(Entry::getKey, i -> BigDecimal.ZERO))))
    .collect(Collectors.toMap(Entry::getKey, Entry::getValue));
Nikolas Charalambidis
  • 40,893
  • 16
  • 117
  • 183
  • There is no need to `map` to a `SimpleEntry` before collecting with `toMap`. What you have written as arguments to the `SimpleEntry` constructor, can be written right into the functions specified to the `toMap` collector (`myMap.entrySet().parallelStream() .collect(Collectors.toMap(Entry::getKey, e -> e.getValue().entrySet().stream() .collect(Collectors.toMap(Entry::getKey, i -> BigDecimal.ZERO)) ));`). – Holger Oct 25 '18 at 16:59
  • So I could conclude that my original code works but changing mutable data it can't be considered purely functional. Anyway it seems to be compliant with stream Javadoc because purely functional behaviour is not explicitly required there. Holger's code is purely functional too. – giuseppe maugeri Oct 25 '18 at 20:48