java8 remove objects from list of objects basis condition

NoobEditor :

Lets say i have a model

Class Travellers{
    private int travellerId;
    private String routeId
    private int came;
    private int gone;
}

so a traveller can go (attribute came) a route and come back (attribute gone). I am trying to remove any traveller who has completed the round trip. Example entry :

id      routeId     came        gone
1       R1          1           0
1       R1          0           1
2       R2          0           1

So R1 should be filtered out and only R2 be left post function

Basically, removeRoundTrips should help me with leaving only folks who have came or gone only.

private List<Travellers> removeRoundTrips(List<Travellers> travellers){
    // right now its a classic 'for' loop here
    // expectation of something like

    travellers.stream()
                .filter( traveller -> someFunctionWhichFilters)
                .collect(Collectors.toList())

}

is there a way to achieve this in streaming / filtering in java8?

Federico Peralta Schaffner :

You first need to merge instances that have the same travellerId and routeId, summing their came and gone attributes. For this, you could have the following utility method in some TravellersUtility helper class:

public final class TravellersUtility {

    private TravellersUtility() { }

    public static Travellers merge(Travellers left, Travellers right) {
        Travellers t = new Travellers();
        t.setRouteId(left.getRouteId());
        t.setTravellerId(left.getTravellerId());
        t.setCame(left.getCame() + right.getCame());
        t.setGone(left.getGone() + right.getGone());
        return t;
    }
}

Then, you could use the above method to reduce your List<Travellers> by using Collectors.toMap:

Map<List<Object>, Travellers> grouped = travellers.stream()
          .collect(Collectors.toMap(
                              t -> Arrays.asList(t.getTravellerId(), t.getRouteId()),
                              Function.identity(),
                              TravellersUtility::merge));

This groups Travellers instances by (travellerId, routeId) pair and merges them when there is any collision, summing their came and gone fields.

Now, we are ready to remove Travellers instances from the values of the map that haven't completed a roundtrip:

grouped.values().removeIf(t -> t.getCame() > 0 && t.getGone() > 0);

To remove such instances, we're using the Collection.removeIf method. If you are OK with a Collection<Travellers>, you're done. If you need a List<Travellers>, simply do:

List<Travellers> result = new ArrayList<>(grouped.values());

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=148097&siteId=1