Skip to content
Advertisement

IllegalStateException: “Duplicate key” for Collectors.toMap()

Reference Question: Numbers which constitute the Maximum sum

I was writing a program which would print the elements which have constituted to the maximum sum. I have been able to pass through any random scenario but when my maximum sum constitutes of two sets, my code fails.

My code:

JavaScript

For example when i am giving a input of 4 5 4 3 , then maximum sum of non adjacent elements is 8 , which would be made from 4 4 or 5 3.

My full code is working fine, just that i am not able to get both results in my final result.

My Error Log:

Exception in thread “main” java.lang.IllegalStateException: Duplicate key 0 at java.util.stream.Collectors.lambda$throwingMerger$0(Collectors.java:133) at java.util.HashMap.merge(HashMap.java:1254) at java.util.stream.Collectors.lambda$toMap$58(Collectors.java:1320) at java.util.stream.ReduceOps$3ReducingSink.accept(ReduceOps.java:169) at java.util.stream.IntPipeline$4$1.accept(IntPipeline.java:250) at java.util.stream.Streams$RangeIntSpliterator.forEachRemaining(Streams.java:110) at java.util.Spliterator$OfInt.forEachRemaining(Spliterator.java:693) at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:481) at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471) at java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:708) at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234) at java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:499) at Ideone.maximumm(Ideone.java:47) at Ideone.main(Ideone.java:27)

Error is pointed to this line: result.add(maxOfSub);

Any help would be nice 🙂

Advertisement

Answer

The reason of this error is that you have a duplicated <key> when you call the Stream.collect(). Remember, this method performs mutable reduction operation on the stream elements. So when your call:

JavaScript

Here, you are defining the <keys> of a Map object as the <values> of Entry<index, values> defined by the Stream.mapToObj() method. Now, when in your data test you have 4, 5, 4, 3, it means, you are trying to create the <key> for the number 4 twice. Therefore, you got this IllegalStateException.

But how can I fix this?

Very simple, just switch the definition of your Map object from <values, indexes> to <indexes, values> in the Stream.collect() call. How can I do this? Well, just replace the Map.Entry::getValue with Map.Entry::getKey and vise versa, like this:

JavaScript

Also, there is better equivalent by using the IntStream.boxed() method. This method returns a Stream consisting of the elements of this stream, each boxed to an Integer. For me this is the best way to convert a List object into a Map object like this:

JavaScript

Notice that I’m using this expression i -> numbers.get(i) > 0 ? numbers.get(i) : 0 to assign the <values> of the Map object. Why are you doing this? Because, we need to track remove the negative numbers so I replaced them with zero. The Stream.filter() method is an alternative, but the Map object will not contain the filtered elements.

However, this modification will affect how you are updating your indexes, because now the map values are the <values> and not <indexes> as shown in this line:

JavaScript

To fix this you just need convert get the <index> from the corespondent <value> like this:

JavaScript

Alternative solution

Now, the above information will only solve the IllegalStateException. However, I found that there is another error. If I use this array of numbers 1, 9, 1, 7, 7, 5, 4, 1, 6, the max sum of non adjacent numbers should be [9 + 7 + 5 + 6] = 27 but your code got [9 + 7 + 6] = 22. So I tried to find a solution for this here:

JavaScript
User contributions licensed under: CC BY-SA
9 People found this is helpful
Advertisement