1

I have two classes:

public class Adegae implements java.io.Serializable {
    private AdegaeId id;
    ...
}

and

public class AdegaeId implements java.io.Serializable {

    private String gpi;
    private String mccode;
    private String aecode;
    ...
}

I also have a list that have elements with duplaicates of aecode:

List<Adegae> adegaes = ...

I'm building my map like so:

Map<String, Adegae> adegaeMap = adegaes.stream()
            .collect(Collectors.toMap(adegae -> adegae.getId().getAecode().trim(), 
                    Function.identity()));

When I run my code I get this exception:

java.lang.IllegalStateException: Duplicate key my.package.Adegae@678e3d87
at java.util.stream.Collectors.lambda$throwingMerger$0(Collectors.java:133)
at java.util.HashMap.merge(HashMap.java:1245)
at java.util.stream.Collectors.lambda$toMap$58(Collectors.java:1320)
at java.util.stream.ReduceOps$3ReducingSink.accept(ReduceOps.java:169)

I wonder if there is a way to collect to a Map by dropping the duplicates at the same time.

serge
  • 1,590
  • 2
  • 26
  • 49
  • 2
    Yes, you need to supply a mergeFunction as the 3rd parameter. See the linked question. – Tunaki Apr 28 '16 at 15:48
  • You would change adegaes from List to Set (Set avoid duplicates), can do something like : List list = ... Set set = new HashSet(list); – Daniel Hernández Apr 28 '16 at 15:55
  • 1
    @DanielHernández Trickier since the duplicates aren't the object themselves but a property of the objects. – Tunaki Apr 28 '16 at 16:03
  • @Tunaki Thank you I upped your answer there - it helped – serge Apr 28 '16 at 16:56
  • Does `Adegae` override the `equals()` method to use their `id` to test equality? If so, this is a slightly different question with a very different answer. Basing equality on the equivalence of ID is a common approach for persistent entities. – erickson Apr 28 '16 at 17:59
  • @erickson Why is it different? `equals` doesn't come into play here. The `mergeFunction` is used when elements are mapped to the same key, which in this case is the id. `equals` is unused. The linked question answers exactly that (`toMap` collector for both) – Tunaki Apr 28 '16 at 18:52
  • @Tunaki It's different because using `distinct()` , if applicable, expresses the intent more clearly and succinctly than a merge operator. Applicability depends on the notion of equality, so `equals()` does come in to play. – erickson Apr 28 '16 at 18:58
  • @erickson Indeed it does come into play for `distinct()` and you're right that it would make sense to have an `equals` comparing the id. – Tunaki Apr 28 '16 at 18:59
  • In the other question: while it's likely `Person` is an entity and *could* be tested by ID, it seems more about merging distinct entities by a business key, like `name`. – erickson Apr 28 '16 at 19:01

2 Answers2

0

You can use the distinct() method on Stream to eliminate the duplicates before further processing.

erickson
  • 265,237
  • 58
  • 395
  • 493
  • Trickier since the duplicates aren't the object themselves but a property of the objects. – Tunaki Apr 28 '16 at 16:03
  • Yes, it depends on the `equals()` method, but here, one would hope that objects with the same ID are equal. – erickson Apr 28 '16 at 17:51
  • 1
    This solution cant apply to my case since this is auto-generated class from Hibernate and I'm using only portion of the whole key. – serge Apr 29 '16 at 14:26
0

Map<String, Adegae> adegaeMap = adegaes.stream() .collect(Collectors.toMap(adegae -> adegae.getId().getAecode().trim(), Function.identity(), (e1, e2) -> e1)); may help in your case

Andrei_N
  • 437
  • 2
  • 15