Ok, I have an object with multiple instance variables that I would like to sort by, so I read that i have to implement a comparator class and use it.
Basically its a plane class with PlaneSeats object as its member.
PlaneSeats has SeatID, CustomerID
I wish to print the occupied seats by CustomerIDs, does anyone know how?
//This Prints it by SeatID (Since it starts from 0)
for (int i = 0; i < seat.length; i++) {
if (seat[i].isOccupied()) {
System.out.println("SeatID " + seat[i].getSeatID() + " assigned to CustomerID " + seat[i].getCustomerID());
}
}
my failed Comparator code is as follows: I hope to NOT use a seperate class though, hopefully so sort of array.sort function?
import java.util.*;
public class Comparator implements Comparator<Plane> {
public int compare(Plane CustomerID[], Plane CustomerID[]) {
}
}
Arrays.sort(CustomerID, new Comparator<Plane>() {
public int compare(Plane p1, Plane p2) {
PlaneSeat ps1 = p1.getPlaneSeat();
PlaneSeat ps2 = p2.getPlaneSeat();
return ps1.getSeatID().compareTo(ps2.getSeatID());
}
});
This will sort on basis of SeatId. If you want to sort on basis of CustomerId, replace getSeatID() with getCustomerID().
This won't compile
public class Comparator implements Comparator<Plane> {
public int compare(Plane CustomerID[], Plane CustomerID[]) {
}
}
You are breaking the contract.
See this code for a possible solution.
PlaneSeat class definition
public class PlaneSeat {
//Create your custom comparator strategy
public static final Comparator<PlaneSeat> CUSTOMER_COMPARATOR = new CustomerComparator();
//fields
private final Integer customerID;
public PlaneSeat(Integer customerID){
this.customerID= customerID;
}
private static class CustomerComparator implements Comparator<PlaneSeat>{
#Override
public int compare(PlaneSeat o1, PlaneSeat o2) {
return o1.customerID.compareTo(o2.customerID);
}
}
#Override
public String toString() {
return "PlaneSeat [customerID=" + customerID + "]";
}
}
Plane class
public class Plane{
private List<PlaneSeat> seats;
public List<PlaneSeat> getSeats() {
return seats;
}
public void setSeats(List<PlaneSeat> seats) {
this.seats = seats;
}
public void sortSeatsByCustomer(){
Collections.sort(seats,PlaneSeat.CUSTOMER_COMPARATOR);
}
#Override
public String toString() {
return "Plane [seats=" + seats + "]";
}
}
Then in your client code:
public static void main(String args []){
List<PlaneSeat> seats = new ArrayList<>();
for(int i =10;i>0;i--)
seats.add(new PlaneSeat(i--));
Plane plane = new Plane();
plane.setSeats(seats);
System.out.println(plane);//print before sorting
plane.sortByCustomers();
System.out.println(plane);//after sorting by customer
}
You shouldn't name your class "Comparator", since that's already a Java interface name.
Plane CustomerID[]
This does not make sense.
Didn't I answer your prior question about seats?
Your PlaneSeat class should implement Comparable<PlaneSeat> and a method named
public int compareTo(PlaneSeat seat)
In this method, seat is the second seat, the object you're comparing with. The other object is
this
In this method, you can call the
getCustomerID()
method on the objects. It should look like:
public int compareTo(PlaneSeat seat) {
if (this.getCustomerID() > seat.getCustomerID()) return 1;
if (this.getCustomerID() < seat.getCustomerID()) return -1;
return 0;
}
If this gives you the reverse order of what you wanted, swap 1 and -1.
Before your comment
//This Prints it by SeatID (Since it starts from 0)
call
seat = Arrays.sort(seat);
to sort the seats.
You can't implement Comparator class again, it's defined as an interface and you have to implement it by naming a different class.
Related
I have three classes in my program. Ship.java, Cabin.java and Passenger.java. According to the program a single cabin can hold upto a maximum of 3 passengers. I'm trying to set passenger details but i keep getting this error
Cannot invoke "classes.Passenger.setFirstName(String)" because
"classes.Main.myShip[0].passenger[0]" is null at
classes.Main.main(Main.java:22)
Ship.java
public class Ship
{
public static Scanner scanner = new Scanner(System.in);
public static Cabin[] myShip = new Cabin[12];
public static void main(String[] args)
{
for (int count = 0; count < 12; count++)
{
myShip[count] = new Cabin();
}
myShip[0].passenger[0].setFirstName("a");
}
}
Cabin.java
public class Cabin
{
int cabinNumber;
Passenger[] passenger = new Passenger[3];
public Cabin()
{
}
public Cabin(int cabinNumber, Passenger[] passenger)
{
this.cabinNumber = cabinNumber;
this.passenger = passenger;
}
public void setCabinNumber(int cNumber)
{
cabinNumber = cNumber;
}
public int getCabinNumber()
{
return cabinNumber;
}
}
Passenger.java
public class Passenger
{
String firstName;
String lastName;
int expenses;
public Passenger()
{
}
//Constructors
public Passenger(String cabinFirstName, String cabinLastName, int pExpenses)
{
firstName = cabinFirstName;
lastName = cabinLastName;
expenses = pExpenses;
}
public void setFirstName(String cabinFirstName)
{
firstName = cabinFirstName;
}
public String getFirstName()
{
return firstName;
}
public void setLastName(String cabinLastName)
{
lastName = cabinLastName;
}
public String getLastName()
{
return lastName;
}
public void setExpenses(int pExpenses)
{
expenses = pExpenses;
}
public int getExpenses()
{
return expenses;
}
}
Please be kind enough to help me out.
Your model is wrong. A ship can (and does) have cabins with no occupants. You have provided no way to have unoccupied cabins. Your cabins need to be fully booked before the ship can be built!
I would consider redefining your Cabin class to be constructed empty -- which means it would have a constructor with a signature like Cabin(), and then provide a way to assign Passengers to Cabins. Maybe this would be a method in the Cabin class, like
boolean assignPassenger(Passenger p) {
... check occupancy...
... return false if full up ...
... otherwise add 'p' to the passenger array ...
... and return true ...
}
You're halfway there in that you're attempting to set the Cabins in the Ship by using a Cabin() constructor -- which is essentially an empty Cabin -- but you have not actually implemented a constructor with that signature.
What I'm getting at here is that, rather than just tweaking some Java, I think you should rethink it a bit. You'd want, I think, to be able to have unoccupied cabins and to be able to determine which cabins are occupied.
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;
}
I am a complete noob (5th day programming) which explains why I have spent countless head-aching hours trying to solve this problem and still have not figured it out yet:
How do you create an instance of CarAndBikes, load it with information of 3 cars and print it out?
Here's my incomplete code to give you an idea of the problem:
public class Vehicle {
String manufacturer, model;
int numberOfWheels;
public Vehicle(String manufacturer, String model, int numberOfWheels) {
this.manufacturer = manufacturer;
this.model = model;
this.numberOfWheels = numberOfWheels;
}
public String getManufacturer() {
return manufacturer;
}
public String getModel() {
return model;
}
public int getNumberOfWheels() {
return numberOfWheels;
}
public String toString() {
return "(" + numberOfWheels +") '" + manufacturer + ", " + model + "'";
}
}
public class CarAndBikes {
private Vehicle[] items;
private int nextFreeItem = 0;
CarAndBikes (int size) {
items = new Vehicle[size];
for(int i = 0; i < size; i++)
items[i] = new Vehicle(manufacturer, model, numberOfWheels);
}
void addVehicle(String man, String mdl, int wheels) {
items[nextFreeItem++].addVehicle(man, mdl, wheels);
}
public String toString() {
return "(" + items + ")";
}
}
public class TestProgram extends CarAndBikes{
TestProgram(int size) {
super(size);
}
public static void main(String[] args) {
Vehicle vehicle1 = new Vehicle("Seat", "Ibiza", 4);
Vehicle vehicle2 = new Vehicle("Reliant", "Robin", 3);
Vehicle vehicle3 = new Vehicle("Honda", "Fireblade", 2);
System.out.println(vehicle1);
System.out.println(vehicle2);
System.out.println(vehicle3);
}
}
In my opinion you'd be better off separating cars and bikes into separating cars and bikes into two seperate classes 'Car' and 'Bike' and then create a 3rd class to house a collection of those objects, that way you can use an List or ArrayList to store them and have a method to just print them out.
import java.util.ArrayList;
Public Class Garage
{
private ArrayList<Vehicle> vehicles;
Public Garage()
{
vehicles = new ArrayList<Vehicle>();
}
public void addVehicle(Vehicle v)
{
vehicles.add(v);
}
public void getVehicles()
{
for(Vehicle v : vehicles)
{
System.out.Println(v.getModel());
}
}
}
You'll notice that the ArrayList accepts objects of type vehicle, well both cars and bikes extend vehicle so they will be accepted.
I notice the toString() method in CarAndBikes is using toString() on an array reference (and arrays don't override toString()). You could use Arrays.toString(Object[]) like
public String toString() {
// return "(" + items + ")";
return Arrays.toString(items);
}
The Object.toString() that you're getting is documented as,
The toString method for class Object returns a string consisting of the name of the class of which the object is an instance, the at-sign character `#', and the unsigned hexadecimal representation of the hash code of the object. In other words, this method returns a string equal to the value of:
getClass().getName() + '#' + Integer.toHexString(hashCode())
Say I have arraylist A and to compare 2 objects of A I do a.getDistanceFromPlayer() < b.getDistanceFromPlayer().
I want to now have list B which will have all of A's objects, but sorted where the first object is closest to player, and last object is furthest.
What might be the fastest way to do this?
Thanks
Have A implement Comparable and then define the method compareTo(Object other) like so:
public int compareTo(Object other) {
if( this.getDistanceFromPlayer() < other.getDistanceFromPlayer() ) {
return -1;
} else if( this.getDistanceFromPlayer() > other.getDistanceFromPlayer()) {
return 1;
}
return 0;
}
Now you can call Collections.sort() on your list of objects
Use Collections.sort with a custom comparator.
eg.
public class DistanceComparator implements Comparator<Integer>{
#Override
public int compare(YourObject o1, YourObject o2) {
if (o1.getDistanceFromPlayer() > o2.getDistanceFromPlayer())
{
return 1;
}
else if (o1.getDistanceFromPlayer() < o2.getDistanceFromPlayer())
{
return -1;
}
return 0;
}
}
Then in your program, call
Collections.sort(YourArrayInstance, new DistanceComparator())
You should make your class implement Comparable.
Then you can use Collections.sort() to sort your List.
If you want a sorted List AND an unsorted List, you'll have to make a copy.
Another option is to create a Comparator.
If you read the documentation for Collections, you'll see it has two sort methods.
One bases the sort on the objects' compareTo method (ie their "natural order").
The other bases the sort on a Comparator that is passed as the second argument.
Here's a link to another question that provides an example implementation of Comparable:
Example implementation of Comparable
Use a Custom Comparator :
B = Collections.sort(A, new CustomComparator());
public class CustomComparator implements Comparator<ClassA> {
#Override
public int compare(final ClassA a, final ClassA b) {
//Make sure you check that neither a nor b are null..
//..
if (a.getDistanceFromPlayer() < b.getDistanceFromPlayer()) {
return 1;
} else if (a.getDistanceFromPlayer() > b.getDistanceFromPlayer()) {
return -1;
}
return 0;
}
}
You can use a custom Comparator and sort your ArrayList, like this:
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
class Main {
public static class Player {
private final float distance;
public Player (final float position) {
this.distance = position;
}
public float getDistanceFrom () {
return distance;
}
#Override
public String toString() {
return "Player [distance=" + distance + "]";
}
}
public static void main(String[] args) throws Exception {
final ArrayList<Player> players = new ArrayList<Player> ();
players.add (new Player (2));
players.add (new Player (5));
players.add (new Player (-3));
players.add (new Player (1));
Collections.sort(players, new Comparator<Player> () {
#Override
public int compare(Player o1, Player o2) {
final float distance1 = o1.getDistanceFrom();
final float distance2 = o2.getDistanceFrom();
return (int) Math.signum (distance1 - distance2);
}
});
System.out.println(players);
}
}
And a fiddle for it.
I've got a public List<FriendProfile> friends = new ArrayList<FriendProfile>();. I initialize the friends list by reading the information from the server. The FriendProfile object contains a int called private int userPosition;
Once the friends list has been initialized, I would like to sort the friends list by having the FriendProfile object with the highest userPosition at index 0 of the list and then sort by accordingly, index 1 with the second highest userPosition ...
I guess I could write an sorting algorithm, yet I'm looking for prewritten code (maybe the JDK has some methods to offer?)
Help is appreciated!
Use Collections.sort() and specify a Comparator:
Collections.sort(friends,
new Comparator<FriendProfile>()
{
public int compare(FriendProfile o1,
FriendProfile o2)
{
if (o1.getUserPosition() ==
o2.getUserPosition())
{
return 0;
}
else if (o1.getUserPosition() <
o2.getUserPosition())
{
return -1;
}
return 1;
}
});
or have FriendProfile implement Comparable<FriendProfile>.
Implement Comparable Interface.
class FriendProfile implements Comparable<FriendProfile> {
private int userPosition;
#Override
public int compareTo(FriendProfile o) {
if(this.userPosition > o.userPosition){
return 1;
}
return 0;
}
}
Just Call the Collection.sort(List) method.
FriendProfile f1=new FriendProfile();
f1.userPosition=1;
FriendProfile f2=new FriendProfile();
f2.userPosition=2;
List<FriendProfile> list=new ArrayList<FriendProfile>();
list.add(f2);
list.add(f1);
Collections.sort(list);
The List will be sorted.
Now no need to Boxing (i.e no need to Creating OBJECT using new Operator use valueOf insted with compareTo of Collections.Sort..)
1)For Ascending order
Collections.sort(temp, new Comparator<XYZBean>()
{
#Override
public int compare(XYZBean lhs, XYZBean rhs) {
return Integer.valueOf(lhs.getDistance()).compareTo(rhs.getDistance());
}
});
1)For Deascending order
Collections.sort(temp, new Comparator<XYZBean>()
{
#Override
public int compare(XYZBean lhs, XYZBean rhs) {
return Integer.valueOf(rhs.getDistance()).compareTo(lhs.getDistance());
}
});
Use Collections.Sort and write a custom Comparator that compares based on userPosition.
use Comparator with Collections.sort method
java.util.Collections.sort(list, new Comparator<FriendProfile >(){
public int compare(FriendProfile a, FriendProfile b){
if(a.getUserPosition() > b.getUserPosition()){
return 1;
}else if(a.getUserPosition() > b.getUserPosition()){
return -1;
}
return 0;
}
});
see this link
There are two ways to do this.
1.
FriendProfile could implement the interface Comparable.
public class FriendProfile implements Comparable<FriendProfile>
{
public int compareTo(FriendProfile that)
{
// Descending order
return that.userPosition - this.userPosition;
}
}
...
Collections.sort(friendProfiles);
2.
You could write a Comparator.
public class FriendProfileComparator implements Comparator<FriendProfile>
{
public int compare(FriendProfile fp1, FriendProfile fp2)
{
// Descending order
return fp2.userPosition - fp1.userPosition;
}
}
...
Collections.sort(friendProfiles, new FriendProfileComparator());
When comparing objects rather than primitives note that you can delegate on to the wrapper objects compareTo. e.g. return fp2.userPosition.compareTo(fp1.userPosition)
The first one is useful if the object has a natural order that you want to implement. Such as Integer implements for numeric order, String implements for alphabetical. The second is useful if you want different orders under different circumstances.
If you write a Comparator then you need to consider where to put it. Since it has no state you could write it as a Singleton, or a static method of FriendProfile.
You can use java.lang.Comparable interface if you want to sort in only One way.
But if you want to sort in more than one way, use java.util.Compartor interface.
eg:
The class whose objects are to be Sorted on its roll_nos
public class Timet {
String name;
int roll_no;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getN() {
return roll_no;
}
public void setN(int n) {
this.roll_no = n;
}
public Timet(String name, int n) {
this.name = name;
this.roll_no = n;
}
public String toString(){
return this.getName();
}
}
The class for sorting:
public class SortClass {
public void go(){
ArrayList<Timet> arr = new ArrayList<Timet>();
arr.add(new Timet("vivek",5));
arr.add(new Timet("alexander",2));
arr.add(new Timet("catherine",15));
System.out.println("Before Sorting :"+arr);
Collections.sort(arr,new SortImp());
System.out.println("After Sorting :"+arr);
}
class SortImp implements Comparator<Timet>{
#Override
public int compare(Timet t1, Timet t2) {
return new Integer(t1.getN()).compareTo (new Integer((t2.getN())));
}
}
public static void main(String[] args){
SortClass s = new SortClass();
s.go();
}
}