Sorting and Binary Search (Java) - java

I was asked to sort a car array by model type and then use Arrays.binarySearch to search for a Car with that Model field. The problem is when the search is conducted it doesn't find anything (even though the model is in there).
Below is my code and output:
import java.util.Arrays;
import java.util.Comparator;
import java.util.Scanner;
public class CarApplication
{
public static void main (String[] args)
{
Scanner keyboard = new Scanner(System.in);
Car car1 = new Car("Toyota", "Corolla" , 1996);
Car car2 = new Car("Nissan", "Murano" , 2004);
Car car3 = new Car("Mazda" , "Miata", 1999);
Car car4 = new Car("Ford", "Mustang" , 2013);
Car car5 = new Car("Chevy", "Volt" , 2020);
Car car6 = new Car("Tesla", "Model X" , 2016);
Car [] myCars = {car1, car2, car3, car4, car5, car6};
Arrays.sort(myCars, new CompareByModel());
System.out.println("Sorting by Model only (Comparator)");
for (Car car:myCars)
System.out.println(car);
System.out.println("Enter the name of the car model you wish to purchase: ");
String model = keyboard.nextLine();
//binary search
Car key = new Car("", model, 0); // set the name field so we can look for a match in array
int location = Arrays.binarySearch(myCars, 0, myCars.length, key, new CompareByModel());
//print message
if (location < 0)
System.out.println("Sorry, please check back next week.");
else
{
System.out.println("We have a " + model + " in location" + myCars[location]);
}
}
}
//Comparator
class CompareByModel implements Comparator<Car>
{
public int compare(Car c1, Car c2) {
int makeResult = c1.getCarMake().compareTo(c2.getCarMake());
int modelResult = c1.getCarModel().compareTo(c2.getCarModel());
return (modelResult == 0) ? makeResult: modelResult;
}
}
Output:
Enter the name of the car model you wish to purchase:
Volt
Sorry, please check back next week.

When you sort, you sort by the make and model, which is cool. But when you try and search, you set the make to "", so the result of comparing the entities won't work correctly.
You could modify the sort Comparator so as to ignore makes with "" when comparing them (so only using models) or supply the make as part of your search or create a seperate "search" Comparator, for example
public class Main {
public static void main(String[] args) {
new Main();
}
public Main() {
Scanner keyboard = new Scanner(System.in);
Car car1 = new Car("Toyota", "Corolla", 1996);
Car car2 = new Car("Nissan", "Murano", 2004);
Car car3 = new Car("Mazda", "Miata", 1999);
Car car4 = new Car("Ford", "Mustang", 2013);
Car car5 = new Car("Chevy", "Volt", 2020);
Car car6 = new Car("Tesla", "Model X", 2016);
Car[] myCars = {car1, car2, car3, car4, car5, car6};
Arrays.sort(myCars, new SortComparator());
System.out.println(Arrays.toString(myCars));
String model = "Murano";
int result = Arrays.binarySearch(myCars, 0, myCars.length, new Car("", model, 0), new ModelComparator());
System.out.println(result);
int location = Arrays.binarySearch(myCars, 0, myCars.length, new Car("", model, 0), new SortComparator());
System.out.println(location);
}
public class Car {
private String make;
private String model;
private int year;
public Car(String make, String model, int year) {
this.make = make;
this.model = model;
this.year = year;
}
public String getMake() {
return make;
}
public String getModel() {
return model;
}
public int getYear() {
return year;
}
#Override
public String toString() {
return getMake() + " " + getModel() + " # " + getYear();
}
}
public static class SortComparator implements Comparator<Car> {
public int compare(Car c1, Car c2) {
int makeResult = c1.getMake().compareTo(c2.getMake());
int modelResult = c1.getModel().compareTo(c2.getModel());
return (modelResult == 0) ? makeResult : modelResult;
}
}
public static class ModelComparator implements Comparator<Car> {
public int compare(Car c1, Car c2) {
return c1.getModel().compareTo(c2.getModel());
}
}
}

Related

How to sort a list of objects by contained enum?

I am using java 8. I have a list of car objects . I want to sort them in a specific order.
each car objects belong to a model . i like to sort the list of car objects by model. The sorted list should be in the following order , cars with models SEDAN, then followed by BMW and then UNICORN.
import java.util.ArrayList;
import java.util.List;
enum Model {
BMW, SEDAN, UNICORN
}
public class Car {
private Model model;
private int id;
public Car(Model model, int id) {
super();
this.model = model;
this.id = id;
}
public Model getModel() {
return model;
}
public void setModel(Model model) {
this.model = model;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public static void main(String[] args) {
List<Car> l = new ArrayList<Car>();
Car c1 = new Car(Model.BMW, 1);
Car c2 = new Car(Model.BMW, 2);
Car c3 = new Car(Model.SEDAN, 3);
Car c4 = new Car(Model.SEDAN, 4);
Car c5 = new Car(Model.SEDAN, 5);
Car c6 = new Car(Model.UNICORN, 6);
Car c7 = new Car(Model.BMW, 7);
Car c8 = new Car(Model.BMW, 8);
l.add(c1);
l.add(c2);
l.add(c3);
l.add(c4);
l.add(c5);
l.add(c6);
l.add(c7);
l.add(c8);
}
}
so when i print the sorted list it should be like this
[Car [model=SEDAN, id=3], Car [model=SEDAN, id=4] ,Car [model=SEDAN, id=5], [model=BMW, id=1], Car [model=BMW, id=2], Car [model=BMW, id=7], Car [model=BMW, id=8], Car [model=UNICORN, id=6]]
How can i achieve this order of sorting on the model enum with a custom comparator.
appreciate if you can help
First approach
Reorder the enum entries so the resulting order follows your requirements:
enum Model {
SEDAN, BMW, UNICORN
}
then you can sort your list as follows:
l.sort(Comparator.comparing(Car::getModel));
Note that enum values are compared by their order in code (i.e. ordinal())
Second approach
Assign a value to each enum entry:
enum Model {
SEDAN(0), BMW(1), UNICORN(2);
final int val;
Model(int val) { this.val = val; }
}
then you can sort your list as follows:
l.sort(Comparator.comparing((Car car) -> car.getModel().val));
You can assign int values to enums and give them values according to the preferences you want.
Then implement Comparable interface for your Car object to sort the using these assigned int values for each model
Code
import java.util.ArrayList;
import java.util.List;
// assign enum values in ascending order here
enum Model {
SEDAN(0),
BMW(1),
UNICORN(2);
private int value;
private Model(int value) {
this.value = value;
}
public int getValue() {
return value;
}
public void setValue(int value) {
this.value = value;
}
}
// implement comparable class
public class Car implements Comparable<Car> {
private Model model;
private int id;
public Car(Model model, int id) {
super();
this.model = model;
this.id = id;
}
public Model getModel() {
return model;
}
public void setModel(Model model) {
this.model = model;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
// compare Cars by Model int value
#Override
public int compareTo(Car otherCar) {
if (this.getModel().getValue() > otherCar.getModel().getValue())
return 1;
else return -1;
}
#Override
public String toString() {
return "Car{" +
"model=" + model +
", id=" + id +
'}';
}
}
public static List<Car> l = new ArrayList<Car>();
Car c1 = new Car(Model.BMW, 1);
Car c2 = new Car(Model.BMW, 2);
Car c3 = new Car(Model.SEDAN, 3);
Car c4 = new Car(Model.SEDAN, 4);
Car c5 = new Car(Model.SEDAN, 5);
Car c6 = new Car(Model.UNICORN, 6);
Car c7 = new Car(Model.BMW, 7);
Car c8 = new Car(Model.BMW, 8);
l.add(c1);
l.add(c2);
l.add(c3);
l.add(c4);
l.add(c5);
l.add(c6);
l.add(c7);
l.add(c8);
l.sort(Car::compareTo);
l;
Output
[Car{model=SEDAN, id=5},
Car{model=SEDAN, id=4},
Car{model=SEDAN, id=3},
Car{model=BMW, id=8},
Car{model=BMW, id=7},
Car{model=BMW, id=2},
Car{model=BMW, id=1},
Car{model=UNICORN, id=6}]

i need to print the list of vehicles that entered on the same date in the parking , user has to enter the date

This is my array list:
private ArrayList<Vehicle> vehicleList;
private int numVehicles;
And this is where i have to print :
public void ListDate(){
Scanner in= new Scanner(System.in);
System.out.println("Enter the day month and year");
System.out.println("Enter the year the vehicle entered the parking");
int year = in.nextInt();
System.out.println("Enter the month the vehicle entered the parking");
int month = in.nextInt();
System.out.println("Enter the day the vehicle entered the parking");
int day = in.nextInt();
DateTime entrytime = new DateTime();
entrytime.setDay(day);
entrytime.setMonth(month);
entrytime.setYear(year);
}
i also need to display a message if no vehicles were parked on that date
This should suit your purposes (if I've understood your question correctly):
class CarPark {
private ArrayList<Vehicle> _vehicles;
public CarPark() {
_vehicles = new ArrayList<Vehicle>();
}
public void addVehicle(Vehicle vehicle) {
_vehicles.add(vehicle);
}
public ArrayList<Vehicle> vehiclesForSpecificDate(DateTime: date) {
ArrayList<Vehicle> filteredVehicles = ArrayList<Vehicle>();
foreach (Vehicle vehicle in _vehicles) {
if (vehicle.EntryTime.Day == date.Day) {
filteredVehicles.add(vehicle);
}
}
return filteredVehicles;
}
}
class Vehicle {
public string Brand { get; set; }
public string Model { get; set; }
public string Registration { get; set; }
public DateTime EntryTime { get; set;}
public Vehicle(String brand, String model, String registration, DateTime entryTime) {
Brand = brand;
Model = model;
Registation = registration
EntryTime = entryTime
}
override public String toString() {
return String.Format("The {0} {1} with registration {2} entered the car park at {3}",
Brand, Model, Registration, EntryTime);
}
}

Objects as arguments

I try to:
Create a Car object in the Main.
Send the object as an argument to the carOwners class.
Print the entire carOwners data from main.
Name and Address will be printed, but not the Car.
What is wrong with my code?
public class TestProgram {
public static void main(String [] args){
Car Saab = createCar();
carOwners guy = createCarOwners (Saab);
printAll(guy);
}
public static Car createCar (){
//user input a, b, c, d
Car temporary = new Car (a, b, c, d);
return temporary;
}
public static carOwners createCarOwners (Car x){
//user input a, b
Car c = x;
carOwners temporary = new carOwners (a, b, c);
return temporary;
}
public static void printAll (carOwners x){
x.printCarData();
x.printNameAddress();
}
}
public class Car {
private String model;
private String Year;
private String licensePlate;
private String color;
public Car (String x, int y, String z, String q){
model = x;
Year = y;
licensePlate = z;
color = q;
}
}
public class carOwners {
private String name;
private String address;
private Car TheCar;
public carOwners (String n, String a, Car b){
name = n;
address = a;
TheCar = b;
}
public void printNameAddress(){
System.out.println();
System.out.println(name);
System.out.println(address);
}
public void printCarData(){
System.out.println(TheCar);
}
}
override toString(), so you can custom the output format of Car
public String toString(){
return "Model :" + this.model + ",Year :" + year;
}
Your Problem is here:
public void printCarData(){
System.out.println(TheCar);
}
You want to print an Object. That doens't work because Java uses the toString-Method for that. If you want to do it like that you have to override the toString()-Method of your car class like that:
public String toString()
{
return "CarModel: " + this.model + ", Production Year: " + year;
}

Java Array storing objects with multiple fields

I have public class Vehicle with two subclasses Car and Truck that each extend Vehicle. The constructor for each class is the same with 3 fields, color, brand and gas mileage.
I've declared an array
Vehicle [] vehArray = new Vehicle[6];
that will store 6 different vehicles. I know a call
Car car1 = new Car("Red", "Ford", 15);
will instantiate car1 with an object of type Car.
How would I store car1 in vehArray[0]?
Try doing something like this:
vehArray[0] = car1;
Shortest way is:
vehArray [0] = new Car("Red", "Ford", 15);
Or even
Vehicle[] vehArray = new Vehicle[]{new Car("Red", "Ford", 15), new Truck("Silver", "Mercedes", 2)};
As below;
1) Test.java;
public class Test {
public static void main(String[] args) {
//Array Initialization with null Vehicle placeholders
Vehicle[] vehicleArray = new Vehicle[6];
//Car class object instances are assiged
for( int i = 0; i < vehicleArray.length; i++ )
vehicleArray[i] = new Car("Red", "Ford", 15+i);
for( int i = 0; i < vehicleArray.length; i++ )
System.out.println
(
i +
" : " + vehicleArray[i].getColor() +
" : " + vehicleArray[i].getBrand() +
" : " + vehicleArray[i].getGasMilage()
);
}
}
2) Vehicle.java
public class Vehicle {
private String color;
private String brand;
private int gasMilage;
public Vehicle() {}
//Constructor with fields
public Vehicle(String color, String brand, int gasMilage) {
this.color = color;
this.brand = brand;
this.gasMilage = gasMilage;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
public String getBrand() {
return brand;
}
public void setBrand(String brand) {
this.brand = brand;
}
public int getGasMilage() {
return gasMilage;
}
public void setGasMilage(int gasMilage) {
this.gasMilage = gasMilage;
}
}
3) Car.java
public class Car extends Vehicle {
//no-arg constructor
public Car() {
super();
}
//field constructor
public Car(String color, String brand, int gasMilage) {
super(color, brand, gasMilage);
}
}
4) Truck.java
public class Truck extends Vehicle {
//no-arg constructor
public Truck() {
super();
}
//field constructor
public Truck(String color, String brand, int gasMilage) {
super(color, brand, gasMilage);
}
}
I suggest declaring all objects of subclasses first then it can be stored in vehicle like so :
Vehicle[] vehicleArray = {ob1,ob2,ob3,ob4,andSo_On};
Do you mean calling parent class constructor so you can use the fields in parent class?
Here's my take :)
Vehicle.java
public class Vehicle {
String color, brand;
int mileage;
Vehicle(String c, String d, int e){
color = c;
brand = d;
mileage = e;
}
}
Car.java
public class Car extends Vehicle{
Car(String c, String d, int e){
super(c, d, e);
}
}
Test.java
public class Test {
public static void main(String[] args) {
Vehicle [] vehArray = new Vehicle[6];
Car car1 = new Car("Red", "Ford", 15);
Car car2 = new Car("Blue", "Audi", 17);
vehArray[0] = car1;
vehArray[1] = car2;
System.out.println("Color: " + car1.color + "\nBrand: " + car1.brand + "\nMileage: " + car1.mileage + "\n");
System.out.println("Color: " + car2.color + "\nBrand: " + car2.brand + "\nMileage: " + car2.mileage);
for(int i=0; i<2; i++) {
if(vehArray[i].color == "Blue")
{
System.out.println("\nCar is " + vehArray[i].brand);
}
}
}
}
I even did testing at the end just to make sure. You're welcome :D

printing out data of array element in java

If I have an array of a class type (cars) and each car has been given a make and model
using set methods, how can I then print out the make and model of a particular element?
I need to print this out in a separate class
public class Car {
private String make;
private String model;
public void setMake (String str1) {
make = str1;
}
public void setModel (String str2) {
model = str2;
}
You need to add a toString() method to your class
public class Car {
private String make;
private String model;
public void setMake (String str1) {
make = str1;
}
public void setModel (String str2) {
model = str2;
}
#Override
public String toString() {
return "Make :"+ make + " Model :" + model;
}
}
Just printing a car
You can then use this as follows
public static void main(String[] args){
Car car=new Car();
car.setMake("Audi");
car.setModel("ModelName");
System.out.println(car);
}
Printing all of an array
Equally if this exists in an array of cars (I'm using the constructor I introduce in the notes for brevity)
public static void main(String[] args){
Car[] cars=new Car[3];
cars[0]=new Car("Audi","ModelName");
cars[1]=new Car("BMW","ModelName");
cars[2]=new Car("Honda","ModelName");
for(int i=0;i<cars.length;i++){
System.out.println(cars[i]);
}
}
Printing after user selects an index
public static void main(String[] args){
Car[] cars=new Car[3];
cars[0]=new Car("Audi","ModelName");
cars[1]=new Car("BMW","ModelName");
cars[2]=new Car("Honda","ModelName");
Scanner scan=new Scanner(System.in);
System.out.println("Select index to print, should be between 0 and " + (cars.length-1));
//checks that user actually inputs an integer,
//checking its in range is left as an excercise
while (scan.hasNextInt()==false){
scan.next(); //consume bad input
System.out.println("Select index to print, should be between 0 and " + (cars.length-1));
}
int index=scan.nextInt();
System.out.println(cars[index]);
}
Notes
It seems like the make and model are essential to the workings of the car class, consider changing your constructor to take them as arguments
public Car(String make, String model){
this.make=make;
this.model=model;
}
All this assumes you already have the element you wish to print
class Car{
String make ;
String model;
#Override
public String toString() {
return "make :"+ this.make + " model :" + this.model;
}
}
List<Car> list= new ArrayList<Car>();
Car c1=new Car();
Car c2=new Car();
Car c3=new Car();
Car c4=new Car();
list.add(c1);
list.add(c2);
list.add(c3);
list.add(c4);
for(Car car : list)
{
System.out.println(car);
}
public class Car {
private String make;
private String model;
public Car(String make, String model) {
this.make = make;
this.model = model;
}
public void setMake (String str1) {
make = str1;
}
public void setModel (String str2) {
model = str2;
}
public String getMake() {
return make;
}
public String getModel() {
return model;
}
}
public class PrintCars {
public static void main(String []args) {
Car cars[] = new Car[10];
// Assume you populate the array with Car objects here by code
cars[0] = new Car("make1", "model1");
for (Car carObj : cars) {
System.out.println(carObj.getmake());
System.out.println(carObj.getmodel());
}
}
}
Try this
private static String toString(sample[] carTypes)
{
StringBuilder stringBuilder = new StringBuilder();
for (int i = 0; i < carTypes.length; i++)
{
if (carTypes[i] != null)
{
stringBuilder.append(" Name : ");
stringBuilder.append(carTypes[i].name);
stringBuilder.append(",");
stringBuilder.append(" Model : ");
stringBuilder.append(carTypes[i].model);
stringBuilder.append(",");
}
}
return stringBuilder.toString().substring(0, stringBuilder.toString().length() - 1);
}
output :
Name : BMW, Model : Mark 3, Name : AUDI, Model : A-6, Name : BENZ, Model : BZ

Categories