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