How to filter dynamically nested list object java 8

跟風遠走 提交于 2021-02-07 22:10:55

问题


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

回答1:


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());



回答2:


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




回答3:


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



来源:https://stackoverflow.com/questions/63312068/how-to-filter-dynamically-nested-list-object-java-8

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!