java OOP sorting data from objects List - java

Long story short, main class consist of
List<Vehicle> vehicles = new ArrayList<Vehicle>();
Car r1 = new Car(1000, true); ...
Cars class is subClass of Vehicles superclass and objects are added to vehicles list. Lastly, the main class calls out
System.out.println(Car.findMostExpensive4x4(vehicles).getPrice());
SubClass "Car" constructor takes in 2 parameters - price and the 4x4 (boolean)
public Car(double pPrice, boolean pfourByFour) {
super(pPrice);
this.fourByFour = pfourByFour;
}
The method that is called out in main has to parse data from object list and return that object. But how is this implemented ?
public static Car findMostExpensive4x4(List<Vehicle> vehicles) {
}
Then, the returned Car object price is found by getPrice method somehow.
public double getPrice() {
return 0;
}
Thank you

The list passed as argument cannot be a Vehicles list, since a Vehicle doesn't know if is 4x4 or not. Cars knows it.
You can create a Vehicle interface:
interface Vehicle {
double getPrice();
boolean is4x4();
}
class Car implements Vehicle {
private double price;
private boolean is4x4;
public Car(double price, boolean is4x4) {
this.price = price;
this.is4x4 = is4x4;
}
#Override
public double getPrice() {
return price;
}
#Override
public double is4x4() {
return is4x4;
}
public static Car findMostExpensive4x4(List<Vehicle> vehicles) {
if (vehicles == null) return null; //or throw exception
if (vehicles.isEmpty()) return null; // or throw exception
double mostExpensivePrice = 0d;
Vehicle mostExpensive = null;
for (Vehicle v : vehicles) {
if (v.is4x4() && v.getPrice() > mostExpensivePrice) {
mostExpensive = v;
mostExpensivePrice = v.getPrice();
}
}
return mostExpensive != null? (Car)mostExpensive : null;
}
}
It is supposed that price cannot be less than 0. In another case, this solution is not valid.
return (Car)mostExpensive; will fail if vehicle is not a Car.
findMostExpensive4x4 method shouldn't be placed in Car class.
This is a fast-thought solution and very ugly, too. You should consider to re-think the design.

Related

Is it possible to create an array which contains objects from several classes that don't necessarily extend each other?

I currently have 7 different classes in my project, with 5 of those classes being related to each other (4 subclasses and 1 superclass) and the other two being related as well (1 subclass and 1 superclass). My assignment asks me to create an array which holds one object from each of these classes. My question is how can I create an array that can hold objects from unrelated classes? Here is a (much) shorter version of my code for example/clarity purposes:
//First superclass
package Plane;
public class Plane {
private String brand;
private double price;
private int horsepower;
public Airplane() {
brand = "example";
price = 700000;
horsepower = 1750;
}
public Airplane(String airplaneBrand, double airplanePrice, int airplanePower) {
this.brand = planeBrand;
this.price = planePrice;
this.horsepower = airplanePower;
}
//Second superclass
package Boat;
public class Boat {
private double weight;
private double price;
public Boat() {
weight = 3475.6;
price = 700000.99;
}
public Boat(double boatWeight, double boatPrice) {
weight = boatWeight;
price = boatPrice;
}
The exact wording of the assignment is "Your array must include at least one object from each of the classes." From my understanding, this is what I described above as having one array that can hold objects from both the Plane class and the Boat class.
The kicker is that I cannot import any of Java's built-in classes (i.e ArrayList, Hash Maps, etc.) I apologize in advance for any clarity issues as I'm only starting out with programming in general, I'd be happy to edit/add information if needed.
In the code provided class is declared as
public class Plane
but constructors created:
public Airplane(){...}
and
public Airplane(String airplaneBrand, double airplanePrice, int airplanePower) {...}
constructor names should be same as class name.
Solution:
Create a Object[] array and use instanceof operator to find the class of the object :
import java.util.*;
class Airplane {
private String brand;
private double price;
private int horsepower;
public Airplane() {
brand = "example";
price = 700000;
horsepower = 1750;
}
public Airplane(String airplaneBrand, double airplanePrice, int airplanePower) {
this.brand = "AirIndia";
this.price = airplanePrice;
this.horsepower = airplanePower;
}
public String getBrand(){
return brand;
}
}
class Boat {
private double weight;
private double price;
public Boat() {
weight = 3475.6;
price = 700000.99;
}
public Boat(double boatWeight, double boatPrice) {
weight = boatWeight;
price = boatPrice;
}
public double getWeight(){
return weight;
}
}
public class Test{
public static void main(String ... $){
var out = System.out;
Object [] array = new Object[5];
array[0] = new Boat();
array[1] = new Airplane();
array[2] = new Boat();
array[3] = new String("Foo loves Bar");
for(var o : array){
if(o instanceof Boat b){
out.println(b.getWeight());
}
if(o instanceof Airplane plane){
out.println(plane.getBrand());
}
if(o instanceof String s){
out.println(s);
}
}
}
}
edit: thanks tgdavies for mentioning the efficient use of instanceof
output:
$ javac Test.java && java Test
3475.6
example
3475.6
Foo loves Bar

Looping through set

I create two classes. The first one (call it Class1) has one private attribute: price. The second one (call it Class2) needs to have a set of objects of Class1:
My code:
private HashSet set = new HashSet<Class1>();
The goal is to create a method in the Class2, which takes an int as an argument and goes through objects to check until it finds one, which has a price equal to a given as an argument number. It needs to return the object. For example, I want to find an object with a price of 500, so I call the function check(500) and it returns exactly that object, which has price of 500. How can I do it?
My code:
public Class1 check(int p)
{
Class1 c = new Class1(p);
Iterator it = set.iterator();
while(it.hasNext())
{
// HERE IS THE HELP NEEDED. Using an array it
// would be sth like if(element[i].price == p)
// but I need to use set
if()
{}
it.next();
}
You can do it like so - however you will need access to the price to be able to compare it. If price itself is private, there should be a getter for it, which I assume in my solution.
public Class1 check(int p) {
for (Class1 c : set) {
if (c.getPrice() == p) return c;
}
return null; // none found
}
In your class Class1, define a getter method
int getPrice() { return price; }
Use it in your class Class2
Class1 curObj = it.next();
if (curObj.getPrice() == p) {
your logic
}
Something like this should work:
public Class1 check(int p) {
Iterator<Class1> it = set.iterator();
while (it.hasNext()) {
Class1 next = it.next();
if (next.getPrice() == p) {
return next;
}
}
return null;
}
I assumed your class Class1 has a getPrice method that returns the price, it is ofcourse impossible to compare the price that we need to find to the price of an object if there is no way to access the field.
Your generic type declaration is incorrect and thus you have a raw type; and you should prefer the Set interface. Something like
private Set<Class1> set = new HashSet<>();
And you can use an enhanced for-each loop to iterate your set items and find a matching price with something like
public Class1 check(int p) {
for (Class1 item : set) {
if (item.getPrice() == p) {
return item;
}
}
return null;
}
Whenever you have private variables, expose them through getter function.
Setters and getters will always help you whenever you will write code with some frameworks like Spring, Hibernate, etc.
public class class2 {
private HashSet set = new HashSet<Class1>();
public Class1 check(int price) {
Iterator<Class1> iterator = set.iterator();
while(iterator.hasNext()) {
Class1 next = iterator.next();
if(next.getPrice() == price)
return next;
}
return null;
}
}
class Class1 {
private int price;
public int getPrice() {
return price;
}
public void setPrice(int price) {
this.price = price;
}
}
You can it iterate the set and in every iteration compare the object against the price parameter, if found return the object, if not return null
Example
public Class1 check(int p)
{
for(Class c : set){
if(c.getPrice ()==p){
return c;
}
}
return null;
}
Add a getter of the price attribute in class1, then the check method can be as follows:
public Class1 check(int p)
{
for (Class1 c1 : set)
{
if (c1.getPrice() == p)
return c1;
}
return null
}

How do I sort an array of objects of different class types?

I am trying to develop a program that can sort an array of objects that are of different class types, but in the same hierarchy as one another. All of the objects are listed within the same array that I am trying to sort, and while I can alphabetically sort an array of objects that are of the same type easily enough, I cannot figure out how to sort everything all at once with the same Arrays.sort() method. Any help that anyone could provide would be greatly appreciated.
import java.util.Arrays;
public class Driver {
public static void main(String[] args) {
Vehicle[] machines = new Vehicle[3];//Example of an array that I can sort
machines[0] = new Vehicle("Giant Robot");
machines[1] = new Vehicle("Time Machine");
machines[2] = new Vehicle("Airplane");
Arrays.sort(machines);
for (int i = 0; i < machines.length; i++)
System.out.println(machines[i].getName());
Vehicle[] vehicles = new Vehicle[7];//example of an array that I cannot sort
vehicles[0] = new Car("Batmobile", 10);
vehicles[1] = new Helicopter("Batcopter", "x");
vehicles[2] = new Car("Jaguar", 6);
vehicles[3] = new Helicopter("RC Copter", "t");
vehicles[4] = new Car("Accelerator", 6);
vehicles[5] = new Helicopter("Stormshadow", "z");
vehicles[6] = new Car("Batmobile", 11);
}
}
**
public class Vehicle implements Comparable {
private String name;
public Vehicle(){
name = "no name";
}
public Vehicle(String newName){
name = newName;
}
public String getName(){
return name;
}
public int compareTo(Object o)
{
if ((o != null) &&
(o instanceof Vehicle))
{
Vehicle otherVehicle = (Vehicle) o;
return (name.compareTo(otherVehicle.name));
}
return -1;
}
}
**
public class Car extends Vehicle {
private int tireSize;
public Car(){
super();
tireSize = 0;
}
public Car(String newName, int newTireSize){
super(newName);
tireSize = newTireSize;
}
public int getSize(){
return tireSize;
}
}
**
public class Helicopter extends Vehicle {
private String bladeType;
public Helicopter(){
super();
bladeType = "none";
}
public Helicopter(String newName, String newBlade){
super(newName);
bladeType = newBlade;
}
public String getType(){
return bladeType;
}
}
Goal: You need to be able to compare a Vehicle to other of Vehicle.
To achieve that goal:
public class Vehicle implements Comparable<? extends Vehicle> {
....
public int compareTo(Object o) {
// Now, that the Comparable is for the type Vehicle
// you know that o is some kind of vehicle
// check vehicle related things
// number of seats, dogs, whatever
return -1;
}
}
You just need to adjust your code to:
class Vehicle implements Comparable<Vehicle> {
private String name;
/* ... */
#Override
public int compareTo(Vehicle vehicle) {
return name.compareTo(vehicle.getName());
}
}
In most cases, your classes should not implement Comparable, unless there is one and only one ordering that is always the correct one, like with numbers. Your vehicles can be sorted by name, by age, and probably by more criteria, so they should not implement Comparable.
Instead, you can pass the ordering function as a lambda function, at the time where you actually sort your vehicles:
Arrays.sort(machines, (left, right) -> left.getName().compareTo(right.getName()));
Or, equivalently:
Arrays.sort(machines, Comparator.comparing(Vehicle::getName));
This way you don’t need the implements Comparable anymore.
If you want to sort by vehicle type then you need to take class type into consideration, while sorting the element. Modify the compareTo() method as shown below:
public int compareTo(Object o){
if ((o != null) &&
(o instanceof Vehicle)){
Vehicle otherVehicle = (Vehicle) o;
return (otherVehicle.getClass().getSimpleName().equals(this.getClass().getSimpleName()) ?
name.compareTo(otherVehicle.name)
: otherVehicle.getClass().getSimpleName().compareTo(this.getClass().getSimpleName()));
}
return -1;
}

What is wrong with these super statements?

I have been working very hard to attempt and figure out these lines of code, but I can never seem to get it to come out right. I get several errors on lines 86, 91, 100, 110 and 118 and I have absolutely no idea why. Anyway, here it is:
public class lab21composition
{
public static void main(String args[])
{
CarFactory factory = new CarFactory ("Ford");
Garage myGarage = new Garage();
Car c = factory.produceCar("Fusion");
Truck t = factory.produceTruck("F150");
System.out.println(myGarage);
myGarage.addVehicle(c);
System.out.println(myGarage);
myGarage.addVehicle(t);
System.out.println(myGarage);
Vehicle v = myGarage.removeVehicle();
if (null !=v)
{
System.out.println(v.toString() + " was removed from garage.");
System.out.println(myGarage);
}
else
{
System.out.println("There was no vehicle in the garage to remove.");
}
myGarage.addVehicle(t);
System.out.println(myGarage);
CarFactory factory2 = new CarFactory ("Honda");
Garage myGarage2 = new Garage();
Car d = factory.produceCar("Odyssy");
myGarage.addVehicle(d);
System.out.println(myGarage2);
}
}
class CarFactory
{
private String name;
public CarFactory(String n)
{
name = n;
}
public Car produceCar(String model)
{
return name;
}
public Truck produceTruck(String model)
{
return name;
}
}
class Vehicle
{
private String make, model;
public Vehicle()
{
make = "Undefined";
model = "Undefined";
}
public Vehicle(String _make, String _model)
{
make = _make;
model = _model;
}
public String toString()
{
return make+" "+model;
}
}
class Car extends Vehicle
{
super (_make,_model); //I get a illegal start of type and identifier expected error here
}
class Truck extends Vehicle
{
super (_make,_model); //I get a illegal start of type and identifier expected error here
}
class Garage
{
//define a private variable that holds a Vehicle object. This will represent
private String Veh;
// the vehicle being stored in the Garage. If the garage is empty, then this variable should be null
}
public void addVehicle(Vehicle v)
{
if(v==Veh) /* replace FALSE with code to check if v is the same as vehicle */
{
//HINT: use a function inherited from the Object class!
System.out.println(v.toString() + " is already parked in this garage")
}
else if (hasVehicle())
{
System.out.println("This garage is full!");
}
else
{
//store the vehicle that was passed to this function
//in this class vehicle attribute
}
}
class removeVehicle()
{
public Vehicle removeVehicle()
{
//store this class vehicle attribute in a temporary variable
// set this class vehicle attribute to null
// return the vehicle stored in the temporary variable
return null;
}
public boolean hasVehicle()
{
//change this return statement so that it
//returns an appropriate boolean value
return false;
}
public String toString()
{
if (hasVehicle())
{
//replace ??? with the toString() method of the vehicle
// that is in this garage
return "This garage has a ??? in it!";
}
else
{
return "This garage is empty.";
}
}
}
class Car extends Vehicle
{
super (_make,_model);
}
The above super call appears outside a constructor. This is syntactically invalid code.
Solution 1: delete this code.
Solution 2: write a constructor.

Java - Scanning Items in an ArrayList

I have a class which creates a 'Purchase' object. This object can be recorded to an ArrayList 'purchaseList' using the recordItem() method. However, I want to create a function that can return a specific Purchase object given an itemNo integer, I have shown my code so far in getPurchase() but am having trouble getting it working.
public class Purchase {
private String name;
private double price;
private int itemNo;
private int sort;
private ArrayList purchaseList = new ArrayList();
public Purchase(String name, double price, int itemNo, int sort) {
this.name = name;
this.price = price;
this.itemNo = itemNo;
this.sort = sort;
}
public void recordItem(int itemNumber, String description, double unitPrice, int sort) {
Purchase newPurchase = new Purchase(description, unitPrice, itemNumber, sort);
purchaseList.add(newPurchase);
}
public int getItemNo() {
return itemNo;
}
public Purchase getPurchase(int itemNumber) {
for(int i = 0; i < purchaseList.size(); i++) {
if(purchaseList[i].getItemNo() == itemNumber) {
return purchaseList[i];
}
else return 0;
}
}
}
purchaseList[i] is valid when you work with arrays.
When working with List objects, to retrieve the ith element, you have to invoke the List.get(int index) method. Like this:
purchaseList.get(i)
And so, your method has to be refactored to:
public Purchase getPurchase(int itemNumber) {
for(int i = 0; i < purchaseList.size(); i++) {
if(purchaseList.get(i).getItemNo() == itemNumber) {
return purchaseList.get(i);
}
else return 0;
}
}
Also, in order to avoid casting from Object to Purchase, you have to make your List generic.
private List<Purchase> purchaseList = new ArrayList<Purchase>();
This way the compiler will ensure that the objects you add to the list are of type Purchase and will not force you to cast them to something specific when being got.
Change your purchaseList[i].getItemNo() to purchaseList.get(i).getItemNo()
Your getPurchase() method logic is incorrect. You shouldn't exit after the first condition is not met.
Try changing it like this:
// Change the declaration like this
private List<Purchase> purchaseList = new ArrayList<Purchase>();
// And change the method like this:
public Purchase getPurchase(int itemNumber) {
for(Purchase purchase : purchaseList) {
if(purchase.getItemNo() == itemNumber) {
return purchase;
}
}
return null;
}
Also recordItem() and getPurchase() don't look like they belong inside the Purchase class.

Categories

Resources