Inf1 OP : Lab Sheet Week 10 Q2 - Shopping Carts
Overview

In this task, we will look at the other comparison interface we introduced in the previous questions: java.util.Comparator.

Like before, the Comparator API provides an abstract method you need to override in your implementation. This method is called compare and takes two arguments of the same data type. It compares them to each other and returns an integer indicating their equality. The return value is a negative integer, zero, or a positive integer as the first argument is less than, equal to, or greater than the second depending on the implementation.

The main difference to the Comparable interface is that comparison of two isntances is now done by a third class. For example, let's say we implement a class CowComparator based on the principles specified above to find out which cow has a higher milk yield.

CowComparator cc = new CowComparator();
Cow A = new Cow(50);
Cow B = new Cow(35);
System.out.println(cc.compare(A,B));
                          

The output of this call would be a positive integer since cow A has a higher milk yield than cow B. Other results follow as before when arguments are swapped around or are the same.

Again, each class implementing this interface has to override the abstract method compare and follow its specified contract as described for the return value. Have a look at the corresponding Java API for more information.

Note

The cases where one or both of the two parameters are null or both are the exact same instance also need to be considered.

Comparing Shopping Carts

In our exercise, we will compare the content of two shopping carts with each other. For example, You mined some data on the shopping behaviour of some of your online shop customers. Now you want to analyse this data by comparing the contents of their shopping carts.

Use the following implementation of the class ShoppingCart which contains a list with all prices of the items it contains. For simplicity, we are not interested in what those items actually are.

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

/**
 * Encapsulates the contents of a shopping cart in an online store.
 */
public class ShoppingCart {

    /** Name of the shopping cart's owner */
    private final String userName;
    /** Prices of items in the shopping cart */
    private final List<Double> itemPrices;

    /**
     * Create a new cart for the given user.
     * @param userName owner of the new cart
     * @throws NullPointerException if given userName is null
     */
    public ShoppingCart(String userName) {
        Objects.requireNonNull(userName);
        this.userName = userName;
        itemPrices = new ArrayList<>();
    }

    /**
     * Add price of item to shopping cart.
     * @param price the price of the item to be added
     * @throws IllegalArgumentException if the price of the given item is negative
     */
    public void addItem(double price) {
        if (price < 0) throw new IllegalArgumentException("Given price must be larger than zero but is: " + price);
        itemPrices.add(price);
    }

    /**
     * Returns the name of this cart's owner.
     * @return the name of this cart's owner.
     */
    public String getUserName() {
        return userName;
    }

    /**
     * Returns a list with all item prices in the cart.
     * @return list with all item prices in the cart.
     */
    public List<Double> getItemPrices() {
       return new ArrayList<>(itemPrices); 
    }

   
    /**
     * Returns a String representation of this cart's state.
     * @return representation of this cart's state.
     */ 
    public String toString() {
        return new StringBuilder()
            .append(userName)
            .append(" :")
            .append(itemPrices)
            .toString();
    }
}

As you can see, the ShoppingCart offers an interface to access its contents via the accessors getUserName and getItemPrices and you can add items to the list with addItem. Furthermore, the toString method is overridden to easily print a human readable format of the classe's state.

Note

Error handling, documentation and proper encapsulation is used as required to protect the class and the developers using it.

Your first task is to implement a class CartComparator which implements the Comparator interface for ShoppingCarts. To make the compiler happy regarding generic requirements, parameterise the Comparator interface in your class signature as follows:

Comparator<ShoppingCart>
  

Implement the necessary abstract method compare as required by the API. Comparison is done based on the average price of all items in the given shopping carts. The cart with the higher average price is considered to be larger and vice versa. If a cart is empty, its average price can be considered zero.

Make sure you return the correct values should any of the parameters be null. For your implementation a null argument should not cause an exception but rather means positive infinity, i.e. infinitely large average value.

Note

We recommend, that you write a tester class with a main method which creates a number of shopping carts with different contents for you to test your implementation. You can also create a list of shopping carts and see if the sort method mentioned above is able to sort them correctly.

An automated test has been created for this exercise: CartComparatorTest.java.

In the second part of this exercise implement a class CartComparatorName which allows you to compare the shopping carts based on the average of it's contents first and, should they turn out to be equal, on the userName second. Name comparison should be done based on the lexicographical ordering of the userName string. Consider the following examples:

Shopping Cart A [ Average: 70, Name: Bert ]
Shopping Cart B [ Average: 40, Name: Adam ]
compare(A,B) returns +1 since the A' average is larger than B's and the names are irrelevant.

Shopping Cart A [ Average: 40, Name: Bert ]
Shopping Cart B [ Average: 40, Name: Adam ]
compare(A,B) returns +1 since the averages are the same and Bert is lexicographically larger than Adam.

Shopping Cart A [ Average: 40, Name: Bert ]
Shopping Cart B [ Average: 40, Name: Bert ]
compare(A,B) returns 0 since the averages and names are equal.
      

Hint

Many Java API classes such as Integer or String implement the Comparable interface already.

Hint

Consider how you can extend the CartComparator from the first part of the question for your second class.

An automated test has been created for this exercise: CartComparatorNameTest.java.