java32776
java32776

Reputation: 31

How to filter dynamically nested list object java 8

How to filter dynamically nested list object java 8

Example:

class Items {
    List<Mobile> mobiles;
}

class Mobile{
    String mName;
    List<Plans> plans;
}

class Plans{
    String planId;
    String planName;
}

So, I have 3 mobiles (mobiles will be dynamic 3 or 4..etc) with multiple plans on each mobile device. How to dynamically filter common plan for each mobile device ?

Example(P1-planId) :
Items:
    M1 - P1,P2,P3,P4
    M2 - P4,P5,P6,P1,P8,P2
    M3 - P7,P2,P4,P1,P8,P9,P10
Result:
Items:
    M1 - P1,P2,P4
    M2 - P1,P2,P4
    M3 - P1,P2,P4

Upvotes: 3

Views: 670

Answers (3)

sprinter
sprinter

Reputation: 27956

A method inside Items to get all plans common to all mobiles might look like:

public List<Plan> getCommonPlans() {
    return mobiles.stream().flatMap(Mobile::streamPlans).distinct()
        .filter(p -> mobiles.stream().allMatch(m -> m.hasPlan(p)))
        .collect(Collectors.toList());
}

this assumes Mobile.streamPlans and Mobile.hasPlan methods which are pretty trivial.

A slightly different method, more efficient but perhaps not so intuitive, is to count the plans and filter for ones that have counts equal to number of mobiles:

    return mobiles.stream().flatMap(Mobile::streamPlans)
        .collect(Collectors.groupingBy(m -> m, Collectors.counting())
        .entrySet().stream()
        .filter(e -> e.getValue() == mobiles.size())
        .map(Map.Entry::getKey)
        .collect(Collectors.toList());

Upvotes: 2

Turing85
Turing85

Reputation: 20185

A slightly different approach would be to:

  • stream all Mobiles,
  • map each Mobile to its List<Plan>s
  • create the union of all plans.

In code, this might look something like this:

HashSet<Plan> initialSet = new HashSet<>(mobiles.get(0).getPlans());
return mobiles.stream()
    .map(Mobile::getPlans)
    .map(HashSet<Plan>::new)
    .reduce(initialSet, (plan1, plan2) -> { 
        plan1.retainAll(plan2);
        return plan1;
    });

Ideone demo

Upvotes: 0

Eklavya
Eklavya

Reputation: 18430

First, take plans of the first mobile and retainAll plans of mobiles from that list.

List<Plans> commonPlans = new ArrayList<>(mobiles.get(0).getPlans());
for (int i = 1; i < mobiles.size(); i++) {
  commonPlans.retainAll(mobiles.get(i).getPlans());
}

Note: Make sure you override equals and hashCode for Plans and check for empty mobiles list

Upvotes: 1

Related Questions