[HD Pg 0, Sec. 12.5.1 - lambda-expressions]

Help and support on OCA OCP Java Programmer Certification Questions
1Z0-808, 1Z0-809, 1Z0-815, 1Z0-816, 1Z0-817

Moderator: admin

Post Reply
flex567
Posts: 202
Joined: Mon Apr 02, 2018 8:40 am
Contact:

[HD Pg 0, Sec. 12.5.1 - lambda-expressions]

Post by flex567 »

I am trying to expand the code from the book(Car example) from Lambda exression to how compiler sees it but I don't exactly how.
What is missing in my code? See the code snippet and my coments.

Code: Select all

import java.util.ArrayList;
import java.util.List;

public class TestClass {

    public static void main( String[] args) {

        //No  Lambda expression
//        CarMall cm = new CarMall();
//        CarFilter cf = new CompanyFilter(" Honda");
//        List<Car> carsByCompany = cm.showCars(cf);
//
//        System.out.println( carsByCompany);

        //Lambda Expression
//        CarMall cm = new CarMall();
//        List < Car > carsByCompany = cm.showCars( c -> c.company.equals(" Honda"));
//        System.out.println( carsByCompany);

        //How compiler sees it
        CarMall cm = new CarMall();
        List <Car> carsByCompany = cm.showCars( new XYZ().showCar()); // I am not sure about this snippet ???
        System.out.println( carsByCompany);

    }
}

class Car {

    String company;
    int year;
    double price;
    String type;

    Car( String c, int y, double p, String t){
        this.company = c;
        this.year = y;
        this.price = p;
        this.type = t;
    }

    public String toString(){ return "(" + company +" "+ year +")"; }
}

class CarMall {
    List<Car> cars = new ArrayList< >();

    CarMall() {
        cars.add(new Car(" Honda", 2012, 9000.0, "HATCH"));
        cars.add(new Car(" Honda", 2018, 17000.0, "SEDAN"));
        cars.add( new Car(" Toyota", 2014, 19000.0, "SUV"));
        cars.add( new Car(" Ford", 2014, 13000.0, "SPORTS"));
        cars.add( new Car(" Nissan", 2017, 8000.0, "SUV"));
    }

    List <Car> showCars( CarFilter cf){
        ArrayList <Car> carsToShow = new ArrayList < >();

        for( Car c : cars){
            if( cf.showCar(c))
                carsToShow.add( c);
        }

        return carsToShow;
    }
}

interface CarFilter {
    boolean showCar( Car c);
}

//class CompanyFilter implements CarFilter {
//    private String company;
//    public CompanyFilter( String c){
//        this.company = c;
//    }
//    public boolean showCar( Car c){
//        return company.equals(c.company);
//    }
//}

class XYZ implements CarFilter {
    public boolean showCar(Car c) {
        return c.company.equals(" Honda");
    }
}


admin
Site Admin
Posts: 10043
Joined: Fri Sep 10, 2010 9:26 pm
Contact:

Re: [HD Pg 0, Sec. 12.5.1 - lambda-expressions]

Post by admin »

> List <Car> carsByCompany = cm.showCars( new XYZ().showCar()); // I am not sure about this snippet ???

Why are you calling .showCar() on XYZ object?
The cm.showCars method expects a CarFilter object. XYZ implements CarFilter and so, new XYZ() is a valid CarFilter object. This is all that you need to pass to cm.showCars. i.e.:

List <Car> carsByCompany = cm.showCars( new XYZ() ); //remove .showCar()

If you look at the code for CarMall's showCar method, you will see that it invokes showCar on the CarFilter object that was passed to this method.
If you like our products and services, please help us by posting your review here.

flex567
Posts: 202
Joined: Mon Apr 02, 2018 8:40 am
Contact:

Re: [HD Pg 0, Sec. 12.5.1 - lambda-expressions]

Post by flex567 »

Aha I think I understad this example.

flex567
Posts: 202
Joined: Mon Apr 02, 2018 8:40 am
Contact:

Re: [HD Pg 0, Sec. 12.5.1 - lambda-expressions]

Post by flex567 »

Can it be said that lambda expression return a reference of an object that implements the method in a way that is implemented in lambda expression?
In case of this is certainly the case:

Code: Select all

List<Car> carsByCompany = cm.showCars(c -> c.company.equals("Honda"));

Code: Select all

c -> c.company.equals("Honda")
returns a reference of an object

admin
Site Admin
Posts: 10043
Joined: Fri Sep 10, 2010 9:26 pm
Contact:

Re: [HD Pg 0, Sec. 12.5.1 - lambda-expressions]

Post by admin »

Yes, that is correct. The code c.company.equals("Honda") goes in the method of the class generated by the compiler.
If you like our products and services, please help us by posting your review here.

flex567
Posts: 202
Joined: Mon Apr 02, 2018 8:40 am
Contact:

Re: [HD Pg 0, Sec. 12.5.1 - lambda-expressions]

Post by flex567 »

So that means that this works:

Code: Select all

Object o = c -> c.company.equals("Honda");
And this as well:

Code: Select all

cm.showCars((CarFilter)o);
?

admin
Site Admin
Posts: 10043
Joined: Fri Sep 10, 2010 9:26 pm
Contact:

Re: [HD Pg 0, Sec. 12.5.1 - lambda-expressions]

Post by admin »

What happend when you tried it out?
Also, how will the compiler know what interface should the class implement. You need to read this topic from the book again thoroughly.
If you like our products and services, please help us by posting your review here.

OCAJO1
Posts: 221
Joined: Mon Nov 26, 2018 2:43 pm
Contact:

Re: [HD Pg 0, Sec. 12.5.1 - lambda-expressions]

Post by OCAJO1 »

The code (whether using lambda shortcut or not) with the CarMall class, is an example of creating a Factory Pattern using an Interface (rather than abstract class), Isn't it?

Also,
As an exercise, try to expand the lambda expression x ->x.price>10000 into a class that implements CarFilter.
Is there a good way to capture the price form Cars List for comparison to 10000, so don't have to rewrite the priceFilter call from main() for each price?

Thanks

admin
Site Admin
Posts: 10043
Joined: Fri Sep 10, 2010 9:26 pm
Contact:

Re: [HD Pg 0, Sec. 12.5.1 - lambda-expressions]

Post by admin »

1. No, it is not an example of factory pattern.
2. Not sure what you are trying to do.
If you like our products and services, please help us by posting your review here.

OCAJO1
Posts: 221
Joined: Mon Nov 26, 2018 2:43 pm
Contact:

Re: [HD Pg 0, Sec. 12.5.1 - lambda-expressions]

Post by OCAJO1 »

1. Hah! It is not, because in CarMall() method different car records have been added, not chosen and returned from different car classes based on the user's choice?

2. Since the prices of the cars are already known in CarMall(), I was going to take the comparison out of the PriceFilter class (code below) and just a have enhanced for loop in the main() that checks the price in each record in CarMall() to see if > 10000, so for example 19000.0 can be replaced with a variable holding the price of the car that is > 10000 in main() method's PriceFilter pf = new PriceFilter(19000.0);

Code: Select all

class PriceFilter implements CarFilter{
    private double price;
    
    public PriceFilter(double p){
        this.price = p;
    }
    
    @Override
    public boolean showCar(Car c){
        if (this.price > 10000)
            return this.price == c.price;
        else
            return false;
    }
}

admin
Site Admin
Posts: 10043
Joined: Fri Sep 10, 2010 9:26 pm
Contact:

Re: [HD Pg 0, Sec. 12.5.1 - lambda-expressions]

Post by admin »

1. yes but you will need to read more about the pattern.
2. ok. sounds good.
If you like our products and services, please help us by posting your review here.

OCAJO1
Posts: 221
Joined: Mon Nov 26, 2018 2:43 pm
Contact:

Re: [HD Pg 0, Sec. 12.5.1 - lambda-expressions]

Post by OCAJO1 »

1. Ok.

2. But, I'm still wondering about my original question
Is there a good way to capture the price from Cars List for comparison to 10000, so don't have to rewrite the priceFilter call from main() for each price?
Thanks

admin
Site Admin
Posts: 10043
Joined: Fri Sep 10, 2010 9:26 pm
Contact:

Re: [HD Pg 0, Sec. 12.5.1 - lambda-expressions]

Post by admin »

Well, that is the reason there is Predicate. You can pass a Predicate to car filter and use a lambda to implement that predicate.
If you like our products and services, please help us by posting your review here.

OCAJO1
Posts: 221
Joined: Mon Nov 26, 2018 2:43 pm
Contact:

Re: [HD Pg 0, Sec. 12.5.1 - lambda-expressions]

Post by OCAJO1 »

Good thing we're not still dealing with java 7 or earlier :D
Last edited by OCAJO1 on Thu May 02, 2019 5:09 pm, edited 1 time in total.

OCAJO1
Posts: 221
Joined: Mon Nov 26, 2018 2:43 pm
Contact:

Re: [HD Pg 0, Sec. 12.5.1 - lambda-expressions]

Post by OCAJO1 »

I played around with combining predicates and making use of already existing car records and came up with the code below,

Code: Select all

import java.util.*;
import java.util.function.Predicate;


class Car{
    String company; int year; double price; String type;
    
    Car(String c, int y, double p, String t){
        this.company = c; this.year = y;
        this.price = p; this.type = t;
    }
    
   @Override
   public String toString() { return "("+company+" "+year+" "+price+")"; }
}

class CarMall {
    
    List<Car> cars = new ArrayList<>();
    
    CarMall(){
        cars.add(new Car("Honda", 2012, 9000.0, "HATCH"));
        cars.add(new Car("Honda", 2018, 17000.0, "SEDAN"));
        cars.add(new Car("Toyota", 2014, 19000.0, "SUV"));
        cars.add(new Car("Ford", 2014, 13000.0, "SPORTS"));
        cars.add(new Car("Nissan", 2017, 8000.0, "SUV"));
    }
    

    List<Car> showCars(Predicate<Car> cf, Predicate<Car> cp, Car c){
        
        ArrayList<Car> carsToShow = new ArrayList<>();
                          
            Predicate<Car> cfp = cf.and(cp);
            if(cfp.test(c)) carsToShow.add(c);

            //this code will show all the cars, except for the ones requested
            //if(!cfp.test(c)) carsToShow.add(c);
            
        return carsToShow;
    } 
}

public class TestClass{

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {        
        
        CarMall cm = new CarMall();

        for (Car v : cm.cars){
            List<Car> carsByCompany = cm.showCars(c -> c.company.equals(v.company),
                                                  c -> c.price > 10000.0,
                                                  v);
           
        if (!carsByCompany.isEmpty()) System.out.println(carsByCompany);
    }
}
Question: Given the original version in the book vs. this one, OOP-wise speaking, is one better than the other or each do their own thing?

Thanks

admin
Site Admin
Posts: 10043
Joined: Fri Sep 10, 2010 9:26 pm
Contact:

Re: [HD Pg 0, Sec. 12.5.1 - lambda-expressions]

Post by admin »

This loop for (Car v : cm.cars){ should be inside showcars method, not in main.
If you like our products and services, please help us by posting your review here.

OCAJO1
Posts: 221
Joined: Mon Nov 26, 2018 2:43 pm
Contact:

Re: [HD Pg 0, Sec. 12.5.1 - lambda-expressions]

Post by OCAJO1 »

But the whole idea of doing it this way was so didn't have to call the showCars method from main() with one hard coded car name after another to check against the price boundary.

Wait a sec., the fact that the user is only providing a price boundary - the requirements have changed. I think I'll create a showCars2 method in carMall class so the user (TestCalss main()) can provide the price boundary to this method and within the method the loop go through the car records checking against the price.

Something like this,

Code: Select all

    List<Car> showCars2(Predicate<Car> cp){
        
        ArrayList<Car> carsToShow = new ArrayList<>();
                      
        for (Car c : cars){
            
            Predicate<Car> cf = d->d.company.equals(c.company);            
            Predicate<Car> cfp = cf.and(cp);
            if(cfp.test(c)) carsToShow.add(c);
            //this code will show all the cars, except for the ones requested
            //if(!cfp.test(c)) carsToShow.add(c); 
 
        }
           
           
        return carsToShow;
    }
This is the call from TestCalss' main()

Code: Select all

        List<Car> carsByCompany2 = cm.showCars2(c->c.price>10000);
        if (!carsByCompany2.isEmpty()) System.out.println(carsByCompany2);
What do you think?
Last edited by OCAJO1 on Fri May 03, 2019 6:14 pm, edited 3 times in total.

admin
Site Admin
Posts: 10043
Joined: Fri Sep 10, 2010 9:26 pm
Contact:

Re: [HD Pg 0, Sec. 12.5.1 - lambda-expressions]

Post by admin »

Yes, better.
If you like our products and services, please help us by posting your review here.

OCAJO1
Posts: 221
Joined: Mon Nov 26, 2018 2:43 pm
Contact:

Re: [HD Pg 0, Sec. 12.5.1 - lambda-expressions]

Post by OCAJO1 »

I took another quick look at it and there is really no reason to call the new method showCars2. Overloading the original showCars method will do the job.

DazedTurtle
Posts: 26
Joined: Wed Oct 02, 2019 1:42 pm
Contact:

Re: [HD Pg 0, Sec. 12.5.1 - lambda-expressions]

Post by DazedTurtle »

Feedback: Maybe I'm just tired, but having similar names for two entirely different methods is throwing me off. I keep having to flip back to the previous pages to see which one is "showCars" and which one is "showCar." It'd help if the interface one was called filterCar or something.

I admit, I'm guilty of using similar names in my own code, but dealing with it when I'm working on it and came up with the names myself is very different from dealing with it while I'm learning about a new concept.

admin
Site Admin
Posts: 10043
Joined: Fri Sep 10, 2010 9:26 pm
Contact:

Re: [HD Pg 0, Sec. 12.5.1 - lambda-expressions]

Post by admin »

Sure, thank you for your feedback. Passed on to the author.
If you like our products and services, please help us by posting your review here.

Post Reply

Who is online

Users browsing this forum: No registered users and 32 guests