Given a class Ball (simplified for this question), where I can not change the equals and hashCode method
class Ball {
String color;
//some more fields, getters, setters, equals, hashcode ..
}
and a list of balls, I want to return true if the list contains at least one ball for each color value "RED", "YELLOW" and "GREEN". Example inputs:
List<Ball> first = List.of(
new Ball("RED"),
new Ball("BLUE"),
new Ball("GREEN"),
new Ball("RED"),
new Ball("YELLOW"),
new Ball("RED"));
List<Ball> second = List.of(
new Ball("RED"),
new Ball("BLUE"),
new Ball("GREEN"),
new Ball("RED"));
expected result for first list is true and for second false. For now I have a classic loop and three counter variables:
private static boolean isValidList(final List<Ball> balls) {
int r = 0;
int y = 0;
int g = 0;
for (Ball ball : balls) {
String color = ball.getColor();
if("RED".equals(color)){
r++;
}
else if("YELLOW".equals(color)){
y++;
}
else if("GREEN".equals(color)){
g++;
}
if(r > 0 && y > 0 && g > 0){
break;
}
}
return r > 0 && y > 0 && g > 0;
}
I have tried to refactor it to use streams like below
private static boolean isValidListStreams(final List<Ball> balls) {
long r = balls.stream().filter(ball -> "RED".equals(ball.getColor())).count();
long y = balls.stream().filter(ball -> "YELLOW".equals(ball.getColor())).count();
long g = balls.stream().filter(ball -> "GREEN".equals(ball.getColor())).count();
return r > 0 && y > 0 && g > 0;
}
but the above need to stream over the list 3 times. Is there a way I can do it in one go? I can't do it with filter using or
return balls.stream()
.filter(ball -> ball.getColor().equals("RED") ||
ball.getColor().equals("YELLOW") ||
ball.getColor().equals("GREEN")).count() >= 3;
since there may be multiple of the same color.