Print average of specific field of arraylist, but filter by another field

So I have a class car, with size and length variables. I have created an arraylist for storing the car objects. I would like to use a java stream to filter the list by size using lambda expression, but then calculate the average of each cars length only. So in the code below I want to get get the average length of cars with a size greater than ten but less than thirty.

I have seen other posts on how to average an arraylist of integers etc, but this is a list of objects that contain integers I cannot get any output, any suggestions greatly appreciated.

import java.util.ArrayList;
import java.util.Arrays;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import java.util.List;


public class Car {
    
        int size;
        int length;
        
        public Car (int s, int l) {
            size = s;
            length = l;
        }
    
        public int getSize() {
            return size;
        }
        
        public int getLength() {
            return length;
        }
        
    
    public static void main(String[]args) {
        ArrayList<Car> list = new ArrayList<Car>();
        Car t1 = new Car(1,5);
        Car t2 = new Car(8,6);
        Car t3 = new Car(12,9);
        Car t4 = new Car(25,12);
        
        list.add(t1);
        list.add(t2);
        list.add(t3);
        list.add(t4);
    
        
         int info = list.stream()
        .filter(l -> l.getSize() > 10 && l.getSize() <30 )
        .average(Car.getLength);
        
            }

}

Upvotes: 0

Views: 312

Answers (1)

Nicholas Leach
Nicholas Leach

Reputation: 165

The ".average()" terminal/aggregate operation in this context is for an IntStream class.

So, instead of calling .average(Car.getLength) (which isn't correct syntax for method reference anyway, assuming that's what you were going for), you need something like:

OptionalDouble average = list.stream()
.filter(l -> l.getSize() > 10 && l.getSize() < 30)
.mapToInt(Car::getLength)
.average();

int avg;

if (average.isPresent(){
   avg = (int) average.getAsDouble();
   System.out.println(avg);
}

That way, once the .average() operation is hit, it is correctly being hit by an IntStream

How you deal with the case where the average value is not present (original streamed list was empty, for ex), is up to you. I didn't initialize the avg variable because I'm assuming you just need it for printing within that conditional, but if you will need it later, you will need to actually initialize it.

https://docs.oracle.com/javase/8/docs/api/java/util/stream/IntStream.html

Some examples of using the average operation: https://www.geeksforgeeks.org/intstream-average-in-java-with-examples/

Upvotes: 1

Related Questions