Question: Lets take a look at my program. That have some imaginary .txt file with car models.

```
public class Car {
    private String model;

    public String getModel() {
        return this.model;
    }
}

public class Main {
    public static void Main(String[] args) {
        ArrayList<Car> cars = loadCars(path); //imaginary func and file
        String someModel = generateSomeModel(); //imaginart func

        for (Car c : cars) 
            if (c.getModel.equals(someModel))
                System.out.println("Hit!");

        for (Car c : cars) 
            if (!c.getModel.equals(someModel))
                System.out.println("Hit!");

    }
}

```

Lets suppose that I have to go through my cars list a 100 times and compare them in if statement for some different attributes every time, that means I will have to write 100 different for loops that will be 90% same. Is there a way to write a function that will take as a parametar Boolean equation? Something like this.

```
public static void printCars(Boolean equation) {
    for (Car c : cars) 
        if (Boolean equation)
            System.out.println("Hit!");
}

```

Answer: 
If you are on Java 8, you could use the [`Stream`](https://docs.oracle.com/javase/8/docs/api/java/util/stream/Stream.html) API with a [`Predicate`](https://docs.oracle.com/javase/8/docs/api/java/util/function/Predicate.html):

```
cars.stream()
    .filter(c -> c.getModel().equals(someModel))
    .forEach(c -> System.out.println("Hit!"));

```

The argument of the `Stream.filter` method is a `Predicate` that is expressed as a lambda expression, in this case `car -> someModel.equals(car.getModel())`.

You can change the lambda expression to match your second example:

```
cars.stream()
    .filter(c -> !c.getModel().equals(someModel))
    .forEach(c -> System.out.println("Hit!"));

```

The way to abstract this to a method is to pass the list, the predicate, and if you want, a [`Consumer`](https://docs.oracle.com/javase/8/docs/api/java/util/function/Consumer.html) that will take some action on the matching elements. Here's some code that you might use as a starting point:

```
public static void handleCars(
        List<Car> cars, 
        Predicate<Car> condition, 
        Consumer<Car> action) {

    cars.stream().filter(condition).forEach(action);
}

```

You can read that line of code as: ***stream the list of cars, filter only the cars that match the given condition and, for each one of them, take the given action***.

And you can invoke the `handleCars` method as follows:

```
handleCars(
    cars, 
    c -> c.getModel().equals(someModel), 
    c -> System.out.println("Car with model " + someModel + " hit!"));

```

Or:

```
handleCars(
    cars, 
    c -> c.getBrand().toLowerCase().contains("mercedes"), // assume brand is String 
    c -> System.out.println("Mercedes model found: " + c.getModel()));

```

As you see, the predicates and the consumers can be as complex as you need.
In case you need to compare you cars with multiple attributes, you need just to override **equals** method for *Car* class.

```
@Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj instanceof Car) {
            Car anotherCar = (Car)obj;
            return this.model.equals(anotherCar.model) &&
                    this.color.equals(anotherCar.color) &&
                    this.year == anotherCar.year;
        }
        return false;
    }

```

This way you will compare all necessary attributes in one step:

```
List<Car> cars = //cars list
Car someCar = //bmw car
for (Car c : cars) {
    if (c.equals(someCar)) {
        System.out.println("Hit!");
    } else {
        System.out.println("Another Hit!");
    }
}

```