Java 8 streams: searching for items from one list matching conditions calculated based on values ​​from another list

They have two classes and two corresponding lists:

class Click {
   long campaignId;
   Date date;
}

class Campaign {
   long campaignId;
   Date start;
   Date end;
   String type;
}

List<Click> clicks = ..;
List<Campaign> campaigns = ..;

And I want to find everything Clickin clicksthat:

  • Do you have a corresponding Campaignto campaignsthe list, ie Campaignwith the same campaignIdAND

  • This one Campaignhas type= "alleged" AND

  • This Campaigns.start< click.date<Campaigns.end

So far I have the following implementation (which seems confusing and complicated to me):

clicks.
        stream().
        filter(click -> campaigns.stream().anyMatch(
                campaign -> campaign.getCampaignType().equals("prospecting") &&
                        campaign.getCampaignId().equals(click.getCampaignId()) &&
                        campaign.getStart().after(click.getDate()) &&
                        campaign.getEnd().before(click.getDate()))).
        collect(toList());

I wonder if there is a simpler solution to the problem.

+6
source share
4 answers

2 : OP . / / . , :

Map<Long, List<Campaign>> map = campaigns.stream().filter(c -> c.type.equals("prospecting"))
                                         .collect(Collectors.groupingBy(c -> c.campaignId));

clicks.stream().filter(k -> map.containsKey(k.campaignId))
               .filter(k -> map.get(k.campaignId).stream().anyMatch(c -> c.start.before(k.date) && c.end.after(k.date)))
               .collect(Collectors.toList());

. O (nm) O (n + m), @Marco13. , StreamEx

Map<Long, List<Campaign>> map = StreamEx.of(campaigns)
                .filter(c -> c.type.equals("prospecting")).groupingBy(c -> c.campaignId);

StreamEx.of(clicks).filter(k -> map.containsKey(k.campaignId))
        .filter(k -> map.get(k.campaignId).stream().anyMatch(c -> c.start.after(k.date) && c.end.before(k.date)))
       .toList();
+4
public List<Click> findMatchingClicks(List<Campaign> cmps, List<Click> clicks) {
    List<Campaign> cmpsProspective = cmps.stream().filter(cmp -> "prospective".equals(cmp.type)).collect(Collectors.toList());
    return clicks.stream().filter(c -> matchesAnyCmp(c, cmpsProspective).collect(Collectors.toList());
}

public boolean matchesAnyCmp(Click click, List<Campaign> cmps) {
     return cmps.stream().anyMatch(click -> cmp.start.before(click.date) && cmp.end.after(click.date));
}

, .

+1

, , , , campaigns. , :

clicks.stream()
    .filter(click -> campaigns.stream()
        .filter(camp -> "prospecting".equals(camp.type))
        .anyMatch(camp -> 
            camp.campaignId == click.campaignId &&
            camp.end.after(click.date) &&
            camp.start.before(click.date)
        )
    )
    .collect(Collectors.toList());

, 1-, , , . , , , :

clicks.stream()
    .filter(click -> campaigns.stream()
        .filter(camp -> "pre".equals(camp.type))
        .anyMatch(camp -> accept(camp, click))
    )
    .collect(Collectors.toList());

static boolean accept(Campaign camp, Click click) {
    return camp.campaignId == click.campaignId &&
            camp.end.after(click.date) &&
            camp.start.before(click.date);
}

, 2 :

+1

Well, there is a very neat way to solve your IMO problem, the original idea coming from Holger (I will find a question and link it here).

You can define your own method that performs the checks (I simplified it a bit):

static boolean checkClick(List<Campaign> campaigns, Click click) {
    return campaigns.stream().anyMatch(camp -> camp.getCampaignId() 
               == click.getCampaignId());
}

And define a function that binds the parameters:

public static <T, U> Predicate<U> bind(BiFunction<T, U, Boolean> f, T t) {
    return u -> f.apply(t, u);
}

And the use will be:

BiFunction<List<Campaign>, Click, Boolean> biFunction = YourClass::checkClick;
Predicate<Click> predicate = bind(biFunction, campaigns);

clicks.stream()
      .filter(predicate::test)
      .collect(Collectors.toList());
+1
source

All Articles