Generics Types and Collections
Rohan Gaikwad and Shreya Ahuja ABopsC Lessons Hacks
Lesson
Unit 1
You are a teenager who has their license and wants to find a car to buy. When you go to the car dealership, you realize that there are many different things you have to keep track of. You have to keep track of the car brands you look at, the prices of the cars, phone numbers of different sales representatives, etc.
To make it easy on yourself, you want to develop a computerized code that is able to sort through different prices, car brands, etc.
The first step to doing this is through storing these different variables just mentioned as data types - primitive data types. You use variables to store data in Java. Types of primitive data include integers, doubles, booleans, etc.
Now, there are so many things you need to make when buying a car: price, brand, milage, color, etc. We can set the price of a car can be stored as a double, the car brand as a strings. If you want to store whether you like a car or not, you can store that information as a boolean data type.
public class Car {
public static void main(String[] args) {
int year = 2023;
double price = 30000.00;
boolean isElectric = true;
System.out.println("Year: " + year);
System.out.println("Price: $" + price);
System.out.println("Is Electric: " + isElectric);
}
}
There are operators like the modulo operator where the remainder is computed or there's division and multiplication. If you ever want to compare car prices, you can set up a code with scanner input which is also a very common with consoles.
import java.util.Scanner;
public class CarPrice {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.print("Enter the price of the car: ");
double price = scanner.nextDouble();
System.out.println("The price of the car is $" + price);
scanner.close();
}
}
We can also use compound operators which follows the form a += 1 or age ++ in order to indicate a = a + 1. For example, if you want to model the amount of cars that have entered the highway. Each time the light turns green the number of cars is car += 2.
int cars = 0; // starting number of cars
int numCarsEntering = 2; // number of cars entering at a time
int numIterations = 5; // number of times to loop
for (int i = 0; i < numIterations; i++) {
cars += numCarsEntering; // use compound operator to add cars
System.out.println("Number of cars on highway: " + cars);
}
public class Hack1 {
public static void main(String[] args) {
int cars = 0; // starting number of cars
int numCarsEntering = 2; // number of cars entering at a time
int numIterations = 5; // number of times to loop
for (int i = 0; i < numIterations; i++) {
cars += numCarsEntering; // use compound operator to add cars
System.out.println("Number of cars on highway: " + cars);
int wheels = cars * 4;
System.out.println("total number of wheels = " + wheels);
}
}
}
Hack1.main(null);
Unit 2
Unit 2 mostly focuses on objects, classes, methods, and constructors.
In order to use the data you need to first create a class. In this class, you can then create objects and methods to access the data.
An object is a reference type and can be used to access data. A constructor makes data that is stored in an object. For example, I can make a car object and create a constructor that includes different characteristics of the car such as its brand, color, price, and milage.
public class Car {
private String brand;
private String color;
private double price;
private double mileage;
public Car(String brand, String color, double price, double mileage) {
this.brand = brand;
this.color = color;
this.price = price;
this.mileage = mileage;
}
// Getters and setters
public String getBrand() {
return brand;
}
public void setBrand(String brand) {
this.brand = brand;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
public double getMileage() {
return mileage;
}
public void setMileage(double mileage) {
this.mileage = mileage;
}
}
Getters and setters use to manipulate the variables. Getters retrieve the variables and setters set the variable.
You can also use methods to make the object perform certain actions. The method includes the scope which indicates if it is public or private allowing other classes/objects to access it or not. There is also the return type. Void does not return any data. Next is the name of the method which usually describes its action. The parameters include what variables are included in the method. Finally, the body actually performs the action.
The method can compare the price of two cars for example. You can create code that outputs the cheaper car when entering the name of the two cars.
public class Car {
private String name;
private double price;
public Car(String name, double price) {
this.name = name;
this.price = price;
}
public String getName() {
return name;
}
public double getPrice() {
return price;
}
public static String cheaperCar(String car1Name, double car1Price, String car2Name, double car2Price) {
Car car1 = new Car(car1Name, car1Price);
Car car2 = new Car(car2Name, car2Price);
if (car1.getPrice() < car2.getPrice()) {
return car1.getName();
} else {
return car2.getName();
}
}
public static void main(String[] args) {
String cheaperCarName = cheaperCar("Toyota", 20000.0, "Honda", 25000.0);
System.out.println("The cheaper car is: " + cheaperCarName);
}
}
It is also important to learn about the math classes. They perform common mathematical functions such as absolute value, exponent power, square root, random number generation, etc.
If acceleration is an important factor in deciding which car you want, absolute value may be important. The car can constantly display your acceleration speed no mater if you are going forward or backward.
public class Acceleration {
public static void main(String[] args) {
double velocity1 = 10.0;
double velocity2 = 5.0;
double time = 2.0;
// Calculate acceleration using absolute value
double acceleration = Math.abs((velocity2 - velocity1) / time);
System.out.println("The acceleration is " + acceleration);
}
}
Maybe there is a whole registry of cars and you do not want to search though each one. Use the random function to randomly display a car and its characteristics to see if it is the right fit.
import java.util.Random;
public class CarRegistry {
public static void main(String[] args) {
// Define car registry
String[] make = {"Honda", "Toyota", "Ford", "Chevrolet", "BMW"};
String[] model = {"Civic", "Camry", "F-150", "Silverado", "X5"};
int[] year = {2015, 2016, 2017, 2018, 2019, 2020};
double[] price = {15000.0, 20000.0, 25000.0, 30000.0, 35000.0, 40000.0};
// Select a random car from the registry
Random rand = new Random();
int index = rand.nextInt(make.length);
String selectedMake = make[index];
String selectedModel = model[index];
int selectedYear = year[rand.nextInt(year.length)];
double selectedPrice = price[rand.nextInt(price.length)];
// Display the selected car and its characteristics
System.out.println("Selected Car: " + selectedMake + " " + selectedModel);
System.out.println("Year: " + selectedYear);
System.out.println("Price: $" + selectedPrice);
}
}
Hack 2
Create a class named "Car" with the following attributes:
make (String) model (String) year (int) price (double) isUsed (boolean) Create a constructor that initializes all of these attributes.
Create a method named "printCarDetails()" that prints out all of the attributes of the car.
In the main method, create an array of three cars with the following details:
Car 1: Make = "Toyota", Model = "Corolla", Year = 2022, Price = 24999.99, isUsed = false Car 2: Make = "Honda", Model = "Accord", Year = 2018, Price = 18999.99, isUsed = true Car 3: Make = "Ford", Model = "Mustang", Year = 2020, Price = 34999.99, isUsed = true Loop through the array and print out the details of each car using the "printCarDetails()" method.
public class CarHack2 {
private String make;
private String model;
private int year;
private double price;
private boolean isUsed;
public CarHack2(String make, String model, int year, double price, boolean isUsed) {
this.make = make;
this.model = model;
this.year = year;
this.price = price;
this.isUsed = isUsed;
}
public void printCarDetails() {
if (isUsed == true) {
System.out.println("Used " + year + " " + make + " " + model + " at a price of $" + price);
}
else {
System.out.println("New " + year + " " + make + " " + model + " at a price of $" + price);
}
}
public static void main(String[] args) {
CarHack2 hack2accord = new CarHack2("Honda", "Accord", 2018, 18999.99, true);
CarHack2 hack2corolla = new CarHack2("Toyota", "Corolla", 2022, 24999.99, false);
CarHack2 hack2mustang = new CarHack2("Ford", "Mustang", 2020, 34999.99, true);
CarHack2[] woocars = new CarHack2[3];
woocars[0] = hack2corolla;
woocars[1] = hack2accord;
woocars[2] = hack2mustang;
for (CarHack2 car : woocars) {
car.printCarDetails();
}
}
}
CarHack2.main(null);
Unit 3
We are going to explore Unit 3 which includes topics like boolean expressions, if statements, control flow, if-else statements, else-if statements, compound boolean expressions, equivalent boolean expressions, and comparing objects. This is roughly 15%-17.5% of the AP Exam.
Just like how cars have different conditions or states, we can use boolean expressions in Java to represent conditions that evaluate to either true or false. For example, we can have a boolean expression that checks if a car's engine is running or if its speed is greater than a certain threshold.
boolean isEngineRunning = true;
int speed = 60;
boolean isSpeedAboveThreshold = speed > 50;
if (isEngineRunning && isSpeedAboveThreshold) {
System.out.println("The car is moving fast!");
} else {
System.out.println("The car is not moving fast.");
}
In Java, we can use boolean operators like && (and), || (or), and ! (not) to create compound boolean expressions that combine multiple conditions. Key to note is the use of truth tables. Oftentimes, if you want to visualize the possible outcomes of different combinations of boolean values and logical operators, and use them to evaluate the overall result of a boolean expression.
One common use of boolean expressions is in if statements, which allow us to execute different blocks of code depending on whether a condition is true or false. This allows us to handle both cases in our code. For example, we can use an if-else statement to check if a car's speed is above a certain limit, and if it is, we can display a warning message.
int speed = 80;
int speedLimit = 60;
if (speed > speedLimit) {
System.out.println("Warning: you are above the speed limit!");
} else {
System.out.println("You are below the speed limit");
}
You can also use else-if statements to check multiple conditions sequentially until one of them is true. This allows you to handle different cases within one code. For example, we can use else-if statements to check the weather condition and adjust the car's driving mode accordingly.
String weather = "rainy";
int visibility = 30;
if (weather.equals("sunny")) {
System.out.println("Driving in normal mode.");
} else if (weather.equals("rainy") && visibility < 50) {
System.out.println("Driving in slow mode due to low visibility.");
} else if (weather.equals("snowy")) {
System.out.println("Driving in snow mode.");
} else {
System.out.println("Driving in normal mode.");
}
Lastly, we can use object comparison to compare objects based on their references. In Java, objects are compared using the == operator, which compares the memory addresses of the objects. For example, we can use object comparison to check if two cars are the same object or not.
public class Car2 {
private String make;
private String model;
public Car2(String make, String model) {
this.make = make;
this.model = model;
}
}
Car2 car1 = new Car2("Toyota", "Camry");
Car2 car2 = new Car2("Toyota", "Camry");
if (car1 == car2) {
System.out.println("car1 and car2 are the same object.");
} else {
System.out.println("car1 and car2 are different objects.");
}
You can also use the equals method which is denoted by equals() to compare two objects.
public static void main(String[] args) {
// Create two Car objects
Car car1 = new Car("Toyota", "Camry", 2020);
Car car2 = new Car("Toyota", "Camry", 2020);
// Compare using equals() method
if (car1.equals(car2)) {
System.out.println("car1 is equal to car2");
} else {
System.out.println("car1 is not equal to car2");
}
}
Hack 3:
- Create a Car object named myCar with the following details:
- Make: "Toyota"
- Model: "Camry"
- Year: 2019
- Price: 25000.0
-
Print the car details using the getMake(), getModel(), getYear(), and getPrice() methods.
-
Check if the car is affordable within a budget of $20000 using the isAffordable() method and print the result using if-else statement.
-
Determine and print the car's classification based on its price using if-else-if statement:
- If the price is greater than $50000, print "The car is a luxury car."
- If the price is greater than $30000, print "The car is a mid-range car."
- Otherwise, print "The car is an affordable car."
public class Car {
private String make;
private String model;
private int year;
private double price;
// Constructor
public Car(String make, String model, int year, double price) {
this.make = make;
this.model = model;
this.year = year;
this.price = price;
}
// Getter methods
public String getMake() {
return make;
}
public String getModel() {
return model;
}
public int getYear() {
return year;
}
public double getPrice() {
return price;
}
// Method to determine if the car is affordable or not
public boolean isAffordable(double budget) {
if (price <= budget) {
return true;
} else {
return false;
}
}
public String isRange() {
if (price >= 50000.00) {
return "The car is a luxury car";
}
else if (price >= 30000.00){
return "The car is a mid-range car";
}
else {
return "The car is an affordable car";
}
}
// Main method
public static void main(String[] args) {
// Create a new Car object
Car hack3 = new Car("Toyota", "Camry", 2019, 25000.00);
// Print the car details
System.out.println(hack3.getMake() + hack3.getModel() + hack3.getYear() + hack3.getPrice());
// Check if the car is affordable with a budget of $20000 using an if-else statement
System.out.println(hack3.isAffordable(50000.00));
// Check if the car is a luxury car based on its price using if-else-if statement
System.out.println(hack3.isRange());
}
}
Car.main(null);
Unit 4
Unit 4 focuses on iteration. Some important topics we will cover are while loops, for loops, and nested iteration. Unit 4 is 17.5-22.5% of the exam.
Just like how cars can keep moving as long as the engine is running, while loops allow us to repeatedly execute a block of code as long as a certain condition is true. Here's an example:
int fuelLevel = 50; // initial fuel level of the car
while (fuelLevel > 0) { // while there is still fuel
System.out.println("Fuel level: " + fuelLevel + " liters"); // print current fuel level
fuelLevel -= 10; // decrease fuel level by 10 liters
}
In this example, the code inside the while loop will keep executing as long as the fuel level is greater than 0. The fuelLevel variable is decreased by 10 in each iteration, and the current fuel level is printed. Once the fuel level reaches 0 or less, the loop will exit.
Issues with while loops:
- If the loop condition is always true, the loop will never exit
- Can easily crash a computer server and should be avoided
- If the loop conditions are always false, then the loop will never run and the body is skipped
Next, let's move on to for loops, which allow us to specify the number of times a block of code should be executed. Just like how cars can go through a fixed number of laps on a racetrack, for loops have a fixed number of iterations.
for (int lap = 1; lap <= 5; lap++) { // for 5 laps
System.out.println("Lap " + lap + " completed!"); // print lap number
}
In this example, the code inside the for loop will be executed 5 times, as specified by the condition lap <= 5. The lap variable is incremented by 1 in each iteration, and the lap number is printed.
Now, let's talk about nested iteration, which is like cars navigating through multiple lanes or roads. Nested iteration involves having one loop inside another loop. Here's an example that has a nested for loop. The outer loop iterates over 3 lanes and the inner loop iterates over 4 cars in each lane. The lane and car variables represent the lane and car numbers, respectively, and their values are printed.
for (int lane = 1; lane <= 3; lane++) { // for 3 lanes
for (int car = 1; car <= 4; car++) { // for 4 cars in each lane
System.out.println("Lane " + lane + ", Car " + car); // print lane and car number
}
}
Break and continue statements help loops too. Break statement will help immediately exit out of the loop. Continue statements help jump to the next iteration.
There's also try-catch statement blocks and exception throwing. Exceptions are signs that something is wrong with the code at runtime and the try-catch statements helps keep the program from crashing. The program tries to run the code assuming it works in the try block and if it catches an exception, it moves to the catch block.
In this example, we have a for loop that iterates over 5 laps. The break statement is used to exit the loop prematurely when the car breaks down on lap 3. The continue statement is used to skip the current iteration and move on to the next lap when the car goes off-track on lap 4. The lap number and corresponding event (completed lap, car broke down, or car went off-track) are printed for each iteration.
for (int lap = 1; lap <= 5; lap++) { // for 5 laps
if (lap == 3) {
System.out.println("Car broke down on lap " + lap + "!");
break; // exit the loop if car breaks down
} else if (lap == 4) {
System.out.println("Car went off-track on lap " + lap + "!");
continue; // skip current iteration and move on to next lap
}
System.out.println("Lap " + lap + " completed!"); // print lap number
}
With this try-catch code example, the method creates a Car class with a displayCarInfo() method that displays the make and year of the car. It also creates a car object and call the displayCarInfo() method. It divides by zero to purposely simulate an error and then the try-catch block catches the ArithmeticException, which is thrown when dividing by zero and prints error message
KEY IDEA: A car may encounter unexpected issues on the road and need to be handled appropriately to avoid crashes or breakdowns.
public class Car {
private String make;
private int year;
public Car(String make, int year) {
this.make = make;
this.year = year;
}
public void displayCarInfo() {
System.out.println("Make: " + make);
System.out.println("Year: " + year);
}
}
public class Main {
public static void main(String[] args) {
try {
Car car = new Car("Toyota", 2020); // Creating a car object
car.displayCarInfo(); // Displaying car information
int speed = 100 / 0; // Trying to divide by zero to simulate an error
} catch (ArithmeticException e) {
System.out.println("Error: Division by zero!"); // Catching and handling the exception
}
}
}
Hack 4
You are tasked with creating a program that allows a user to enter the number of cars they own, and then input the make and model of each car. The program will then print out the list of cars.
Here are the specific requirements:
- Use a try-catch statement to catch any input/output exceptions that may occur.
- Use a while loop to ensure that the user enters a positive integer for the number of cars they own.
- Use a for loop to iterate over each car and prompt the user to enter the make and model of the car.
import java.util.Scanner;
import java.util.ArrayList;
public class MonkeyCar {
public String make;
public String model;
public int monkeymonknum = 0;
public MonkeyCar(String make, String model) {
this.make = make;
this.model = model;
}
public String getMake() {
return this.make;
}
public String getModel() {
return this.model;
}
public void setMake(String newMake) {
this.make = newMake;
}
public void setModel(String newModel) {
this.model = newModel;
}
public String toStringCar() {
return ("the make is " + this.make + " and the model is " + this.model);
}
public void printArrayList() {
}
public static void main(String[] args) {
ArrayList<MonkeyCar> monkeycarlist = new ArrayList<MonkeyCar>();
Scanner monkeymonk = new Scanner(System.in);
int monkeymonknum = monkeymonk.nextInt();
try {
while (monkeymonknum > 0) {
for (int i=0; i < monkeymonknum; i++) {
String a = monkeymonk.nextLine();
String b = monkeymonk.nextLine();
MonkeyCar car = new MonkeyCar(a, b);
monkeycarlist.add(car);
}
monkeymonknum -= 1;
}
for (int y=0; monkeycarlist.size() > y; y++) {
System.out.println((monkeycarlist.get(y)).toStringCar());
}
} catch (Exception e) {
System.out.println("error");
}
}
}
MonkeyCar.main(null);