curious_brain
curious_brain

Reputation: 403

List of unique objects containing unique sub-objects

I am trying to get a list of unique objects where each object further contains a list of unique sub-objects. Uniqueness in below example is determined by the id field in each class.

public class MyMain {
    public static void main(String[] args) {
        Parent p1 = new Parent(1L);
        Child c11 = new Child(11L);
        Child c12 = new Child(12L);

        Parent p2 = new Parent(2L);
        Child c21 = new Child(21L);
        Child c22 = new Child(22L);
        Child c23 = new Child(23L);

        Holder holder1 = new Holder(p1.getId(), c11.getId());
        Holder holder2 = new Holder(p1.getId(), c11.getId());
        Holder holder3 = new Holder(p1.getId(), c11.getId());
        Holder holder4 = new Holder(p1.getId(), c11.getId());
        Holder holder5 = new Holder(p1.getId(), c12.getId());
        Holder holder6 = new Holder(p1.getId(), c12.getId());
        Holder holder7 = new Holder(p1.getId(), c12.getId());

        Holder holder8 = new Holder(p2.getId(), c21.getId());
        Holder holder9 = new Holder(p2.getId(), c21.getId());
        Holder holder10 = new Holder(p2.getId(), c21.getId());
        Holder holder11 = new Holder(p2.getId(), c22.getId());
        Holder holder12 = new Holder(p2.getId(), c23.getId());
        Holder holder13 = new Holder(p2.getId(), c23.getId());

        List<Holder> holders = new ArrayList<>();
        holders.add(holder1); holders.add(holder2); holders.add(holder3); holders.add(holder4);
        holders.add(holder5); holders.add(holder6); holders.add(holder7); holders.add(holder8);
        holders.add(holder9); holders.add(holder10); holders.add(holder11); holders.add(holder12); holders.add(holder13);
    }
}

@Value
@EqualsAndHashCode(onlyExplicitlyIncluded = true)
class Parent {
    @EqualsAndHashCode.Include
    public Long id;
    public List<Child> chidren;

    public Parent(Long id) { this.id = id; }
}

@Value
@EqualsAndHashCode(onlyExplicitlyIncluded = true)
class Child {
    @EqualsAndHashCode.Include
    public Long id;

    public Child(Long id) { this.id = id; }
}

@Value
class Holder {
    Long parentId;
    Long childId;

    public Holder(Long parentId, Long childId) {
        this.parentId = parentId;
        this.childId = childId;
    }
}

From the code fragment above, I am looking to get a List<Parent> (from holders ) that will contain two parents: p1 and p2. Each parent will then have a List<Child> containing unique children for that parent.

Expected output:

List<Parent> will have p1 and p2
p1.List<Child> will have c11 and c12 (only 2 entries)
p2.List<Child> will have c21, c22, c23 (only 3 entries)

I have worked out how to get a list of unique parents but not sure how to achieve unique children as well.

UPDATE:

Below seems to be working for me, however, not sure if there's a better way.

public class MyMain {
    public static void main(String[] args) {
        MyMain m = new MyMain();
        Parent p1 = new Parent(1L, null);
        Child c11 = new Child(11L);
        Child c12 = new Child(12L);

        Parent p2 = new Parent(2L, null);
        Child c21 = new Child(21L);
        Child c22 = new Child(22L);
        Child c23 = new Child(23L);

        Holder holder1 = new Holder(p1.getId(), c11.getId());
        Holder holder2 = new Holder(p1.getId(), c11.getId());
        Holder holder3 = new Holder(p1.getId(), c11.getId());
        Holder holder4 = new Holder(p1.getId(), c11.getId());
        Holder holder5 = new Holder(p1.getId(), c12.getId());
        Holder holder6 = new Holder(p1.getId(), c12.getId());
        Holder holder7 = new Holder(p1.getId(), c12.getId());

        Holder holder8 = new Holder(p2.getId(), c21.getId());
        Holder holder9 = new Holder(p2.getId(), c21.getId());
        Holder holder10 = new Holder(p2.getId(), c21.getId());
        Holder holder11 = new Holder(p2.getId(), c22.getId());
        Holder holder12 = new Holder(p2.getId(), c23.getId());
        Holder holder13 = new Holder(p2.getId(), c23.getId());

        List<Holder> holders = new ArrayList<>();
        holders.add(holder1); holders.add(holder2); holders.add(holder3); holders.add(holder4);
        holders.add(holder5); holders.add(holder6); holders.add(holder7); holders.add(holder8);
        holders.add(holder9); holders.add(holder10); holders.add(holder11); holders.add(holder12); holders.add(holder13);

        Map<Long, Set<Long>> returnSet= holders.stream()
                .collect(Collectors.toMap(Holder::getParentId, x -> m.uniqChildIdSet(x), MyMain::merge));

        System.out.println(returnSet);
    }

    public static Set<Long> uniqChildIdSet(Holder holder) {
        HashSet<Long> uniqChild = new HashSet();
        uniqChild.add(holder.getChildId());
        return uniqChild;
    }

    public static Set<Long> merge(Set<Long> l1, Set<Long> l2) {
        l1.addAll(l2);
        return l1;
    }
}

@Value
@EqualsAndHashCode(onlyExplicitlyIncluded = true)
class Parent {
    @EqualsAndHashCode.Include
    public Long id;
    public List<Child> chidren;

    public Parent(Long id, List<Child> chidren) { this.id = id;
        this.chidren = chidren;
    }
}

@Value
@EqualsAndHashCode(onlyExplicitlyIncluded = true)
class Child {
    @EqualsAndHashCode.Include
    public Long id;

    public Child(Long id) { this.id = id; }
}

@Value
class Holder {
    Long parentId;
    Long childId;

    public Holder(Long parentId, Long childId) {
        this.parentId = parentId;
        this.childId = childId;
    }
}

Upvotes: 0

Views: 164

Answers (1)

Yassin Hajaj
Yassin Hajaj

Reputation: 21995

Here is what you could use, without any helper methods.

What it's basically doing is the following

  1. Group by the Holder's parent id
  2. For this Holder, take all the childId properties and put them in a Set<Long>
Map<Long, Set<Long>> returnSet =  holders.stream()
                                         .collect(Collectors.groupingBy(
                                                      Holder::getParentId, 
                                                      Collectors.mapping(
                                                          Holder::getChildId, 
                                                          Collectors.toSet()
                                                      )
                                                  )
                                              );

Output

{1=[11, 12], 2=[21, 22, 23]}

Upvotes: 1

Related Questions