So I've been trying to figure out how Collections work in Java (by looking at an old project we did in uni) but I keep getting some errors I cannot fix, it has something to do with the Comparable function
This is my first class:
import java.io.*;
import java.util.*;
public class Client {
private int hour;
private int minute;
private int min_per_stay;
private double price;
public Client(int h, int m, int mps, double p)
{
this.hour = h;
this.minute = m;
this.min_per_stay = mps;
this.price = p;
}
public void SetHour(int h)
{
this.hour = h;
}
public void SetMin(int m)
{
this.minute = m;
}
public void SetMinPStay(int mps)
{
this.min_per_stay = mps;
}
public void SetPrice(double p)
{
this.price = p;
}
public int GetHour()
{
return hour;
}
public int GetMin()
{
return minute;
}
public int GetMinPStay()
{
return min_per_stay;
}
public double GetPrice()
{
return price;
}
public String toString()
{
return "Hours: " + this.hour +
" Minutes: " + this.minute +
" Minutes per stay:" + this.min_per_stay +
" Price: " + this.price + "\n";
}
public boolean equals(Client c) {
return (this.hour == ((Client)c).GetHour() && this.minute == ((Client)c).GetMin());
}
public int CompareTo(Client c)
{
if (this.hour<((Client)c).hour) return -1;
if(this.minute<((Client)c).minute) return -1;
if (this.hour>((Client)c).hour) return 1;
if(this.minute>((Client)c).minute) return 1;
return 0;
}
}
And my collection:
import java.io.*;
import java.util.*;
public class ClientCollection{
private SortedSet<Client> oClient = new TreeSet<Client>();
public ClientCollection()
{
}
public ClientCollection(String FileName)
{
try
{
Scanner sc = new Scanner(new File(FileName));
while(sc.hasNextLine())
{
oClient.add(new Client(sc.nextInt(),sc.nextInt(),
sc.nextInt(),sc.nextDouble()));
}
sc.close();
}
catch (FileNotFoundException e)
{
System.out.println("File not found!");
}
}
public void addClient(Client c)
{
oClient.add(c);
}
public List<Client> reverseList()
{
List<Client> oList1 = new ArrayList<Client>(oClient);
List<Client> oList2 = new ArrayList<Client>();
for(ListIterator<Client> it = (oList1.listIterator(oClient.size())); it.hasPrevious(); )
{
Client res = it.previous();
oList2.add(res);
}
return oList2;
}
public void printColl()
{
System.out.println(oClient.toString());
}
public static void main(String[] args)
{
ClientCollection oc = new ClientCollection("test.txt");
oc.printColl();
oc.reverseList();
oc.printColl();
}
}
and the errors I get are:
Exception in thread "main" java.lang.ClassCastException: Client cannot be cast to java.base/java.lang.Comparable
at java.base/java.util.TreeMap.compare(Unknown Source)
at java.base/java.util.TreeMap.put(Unknown Source)
at java.base/java.util.TreeSet.add(Unknown Source)
at ClientCollection.<init>(ClientCollection.java:20)
at ClientCollection.main(ClientCollection.java:56)
i'll be really happy if someone explains the errors to me, im still kinda new at this :(
Your Client class doesn't implement the Comparable<Client> interface (i.e. Client doesn't have a natural ordering).
Therefore, in order for it to be used as an element of a TreeSet, you must pass to the TreeSet<Client> constructor a Comparator<Client>, which specifies the ordering of Client elements.
Failing to do so results in ClassCastException, since the TreeSet class (or rather the TreeMap class that is uses behind the scenes) assumes that if you didn't supply a Comparator in the constructor, this means that your Client implements Comparable.
EDIT: Since you have a CompareTo method in the Client class, it looks like you intended to implement Comparable.
Change:
public class Client
to:
public class Client implements Comparable<Client>
and change:
public int CompareTo(Client c)
to:
public int compareTo(Client c)
You might want to modify the logic of your compareTo method, though.
Apart from what #Eran wrote, you need to write method names starting with a lower case letter. You can see that StackOverflow's formatter gets confused by it. It will also confuse anybody having to maintain your code.
Your compareTo method should look like this:
public int compareTo(final Client c)
{
final int diffHours = this.hour - c.hour;
if (diffHours == 0) {
return this.minute - c.minute;
} else {
return diffHours;
}
}
The casts are unnecessary, since the c parameter is already of type Client.
Related
I need to make a programm which is like a rally, theres 2 types of vehicles, motorcycle and cars, two types of motorcycle, with and without sidecar, the thing is that I need to verify if there is just a motorcycle in an array list, I mean, two wheels vehicle. That verification should be done in a method called esDe2Ruedas(), which is called by an abstract overrided method called check() that should be the one that verifies if a group of vehicles from an array are able to run in the rally, if its true all the elements of the array must be from the same type.
Here is the code
this is how the program arrays the vehicles
GrandPrix gp1 = new GrandPrix();
gp1.agregar(v1);
//gp1.mostrar(v1);
gp1.agregar(v2);
System.out.println(gp1.check());
GrandPrix gp2 = new GrandPrix();
gp2.agregar(vt1);
gp2.agregar(vt2);
gp2.agregar(m2);
System.out.println(gp2.check());
GrandPrix gp3 = new GrandPrix();
gp3.agregar(vt1);
gp3.agregar(vt2);
gp3.agregar(m1);
System.out.println(gp3.check());
GrandPrix gp4 = new GrandPrix();
gp4.agregar(m1);
gp4.agregar(m2);
System.out.println(gp4.check());
This is the class that is using
import java.util.ArrayList;
public class GrandPrix extends Rally{
ArrayList<Vehiculo> ve = new ArrayList<Vehiculo>();
public void agregar(Vehiculo v) {
ve.add(v);
}
public void agregar(Carro c) {
ve.add(c);
}
public void agregar(Moto m) {
ve.add(m);
}
#Override
boolean check() {// HERE I VERIFY IF THE VEHICLES ARE COMPATIBLE
return false;
}
}
This is the class where everything goes on
public class Vehiculo {
private String Nombre;
private double velocidad_max;
private int peso;
private int comb;
public Vehiculo() {
setNombre("Anónimo");
setVel(130);
setPeso(1000);
setComb(0);
}
public Vehiculo(String string, double d, int i, int j) {
setNombre(string);
setVel(d);
setPeso(i);
setComb(j);
}
double rendimiento() {
return velocidad_max/peso;
}
public boolean mejor(Vehiculo otroVehiculo) {
return rendimiento()>otroVehiculo.rendimiento();
}
public String toString() {
return getNombre()+"-> Velocidad máxima = "+getVel()+" km/h, Peso = "+getPeso()+" kg";
}
/**************************************
---------SET And GET Nombre------------
***************************************/
public String getNombre() {
return Nombre;
}
public void setNombre(String nuevoNombre) {
this.Nombre=nuevoNombre;
}
/**************************************
---------SET And GET velocidad_max------------
***************************************/
public double getVel() {
return velocidad_max;
}
public void setVel(double nuevaVel) {
this.velocidad_max=nuevaVel;
}
/**************************************
---------SET And GET peso------------
***************************************/
public double getPeso() {
return peso;
}
public void setPeso(int nuevoPeso) {
this.peso=nuevoPeso;
}
/**************************************
---------SET And GET comb------------
***************************************/
public int getComb() {
return comb;
}
public void setComb(int comb) {
this.comb = comb;
}
boolean esDe2Ruedas() {
return false;
}
}
This is the class of motorcycles, which is in theory the same as the car's class, without sidecar thing
public class Moto extends Vehiculo{
private boolean sidecar;
public Moto(String string, double d, int i, int j) {
setNombre(string);
setVel(d);
setPeso(i);
setComb(j);
setSidecar(false);
}
public Moto(String string, double d, int i, int j, boolean b) {
setNombre(string);
setVel(d);
setPeso(i);
setComb(j);
setSidecar(b);
esDe2Ruedas(false);
}
public String toString() {
String str = null;
if(isSidecar())
str =super.toString()+", Moto, con sidecar";
else
str =super.toString()+", Moto";
return str;
}
public boolean isSidecar() {
return sidecar;
}
public void setSidecar(boolean sidecar) {
this.sidecar = sidecar;
}
I guess what you presented is what is given. If you came up with the design it is ok, but I believe it could be improved. Anyway, I try to respond to what I believe was your question straight away.
Vehiculo is the super type of Moto (which can have a side car and becomes 3 wheeler).
Vehiculo has a method esDe2Ruedas, which returns false.
Moto inherits that method <-- this is wrong, it should override it and, depending on side car, return the expected boolean value.
In the check method you can now distinguish between Moto and "Moto with sidecar" by using that method.
I'm doing an exercise, in which I have to create the method add, however due to p and v being defined as objects, I'm having a hard time figuring out how I can define this method in the syntax I've been given in the exercise (I'm only allowed to change the methods).
I would like to add the two inputs 5 and 17 so that it returns 22. I've done a lot of research into other questions where I've seen them write it as Positiv(p + v) but this doesn't quite work.
public class Positiv {
public static void main(String[] args) {
try {
Positiv p = new Positiv(5);
Positiv v = new Positiv(17);
p.add(v);
System.out.println(p.get());
} catch (Exception e) {
e.printStackTrace();
}
}
private int n;
public Positiv(int n) {
if (n < 0) { throw new IllegalArgumentException("exception");
}
this.n = n;
}
public static Positiv add(Positiv v)
{
return new Positiv(n + v);
}
public int get() {
return n;
}
}
In your add method:
public static Positiv add(Positiv v)
{
return new Positiv(n + v);
}
You return a whole new Positiv object. However (correct me if I'm wrong) it looks as if you just want to add the two n fields. You can do this by adding this.get to v.get:
public void add(Positiv v)
{
this.n += v.get();
}
Which will return 22
Tutorial for this
public class HelloWorld{
public static void main(String []args){
Numbers a = new Numbers(5);
Numbers b = new Numbers(10);
int num1 = a.getN();
int num2 = b.getN();
System.out.println(addTwoNumbers(num1, num2));
}
public static int addTwoNumbers(int a, int b) {
return a + b;
}
}
class Numbers {
private int n;
public Numbers(int n) {
this.n = n;
}
public int getN() {
return n;
}
}
Apologies if this is trivial to most but I just can't figure this issue out!!
I am creating a mock game where I have a start, end, and hops along. There are portals where if you go on a white portal you jump further ahead and there are black ones where you go backwards. I have set up the class as a POJO;
private int totalSize;
private int minDice;
private int maxDice;
private int whitePortalStart;
private int whitePortalEnd;
private int blackPortalStart;
private int blackPortalEnd;
private int startPosition = 1;
private int currentPosition;
public GameObject(){}
public int getTotalSize() {
return totalSize;
}
public void setTotalSize(int totalSize) throws Exception {
if(totalSize <= 0){
throw new Exception("Can't have a total distance of less than or equal to 0");
} else {
this.totalSize = totalSize;
}
}
public int getMinDice() {
return minDice;
}
public void setMinDice(int minDice) throws Exception {
if(minDice <= 0){
throw new Exception("Can't have a min dice value of less than or equal to 0");
} else {
this.minDice = minDice;
}
}
public int getMaxDice() {
return maxDice;
}
public void setMaxDice(int maxDice) throws Exception {
if(getMinDice() > maxDice){
throw new Exception("Cant have minimum dice number greater than the larger dice number");
} else {
this.maxDice = maxDice;
}
}
public int getWhitePortalStart() {
return whitePortalStart;
}
public void setWhitePortalStart(int whitePortalStart) throws Exception {
this.whitePortalStart = whitePortalStart;
}
public int getWhitePortalEnd() {
return whitePortalEnd;
}
public void setWhitePortalEnd(int whitePortalEnd) throws Exception {
this.whitePortalEnd = whitePortalEnd;
}
public int getBlackPortalStart() {
return blackPortalStart;
}
public void setBlackPortalStart(int blackPortalStart) throws Exception {
this.blackPortalStart = blackPortalStart;
}
public int getBlackPortalEnd() {
return blackPortalEnd;
}
public void setBlackPortalEnd(int blackPortalEnd) throws Exception {
this.blackPortalEnd = blackPortalEnd;
}
public GameObject builder(int n) throws Exception {
setTotalSize(n);
return this;
}
public GameObject whitePortal(int m, int o) throws Exception {
setWhitePortalStart(m);
setWhitePortalEnd(o);
return this;
}
public GameObject blackPortal(int o, int m) throws Exception {
setBlackPortalStart(o);
setBlackPortalEnd(m);
return this;
}
public GameObject dice(int i, int j) throws Exception {
setMinDice(i);
setMaxDice(j);
return this;
}
public int rollDice(){
Random random = new Random();
int min = getMinDice();
int max = getMaxDice();
return random.nextInt(max - min + 1) + min;
}
public void build(){
int totalDistance = getTotalSize();
currentPosition = startPosition;
while(currentPosition < totalDistance){
int diceValue = rollDice();
if(currentPosition + diceValue > getTotalSize()){
System.out.println("CurrentPosition : " + (currentPosition + diceValue) + ", is larger than the total size of the road - " + totalSize);
continue;
} else if(currentPosition + diceValue == getWhitePortalStart()){
System.out.println("You landed on a white portal. Advancing from position " + (currentPosition + diceValue) + " to " + getWhitePortalEnd());
currentPosition = getWhitePortalEnd();
} else if(currentPosition + diceValue == getBlackPortalStart()){
System.out.println("You landed on a black portal. Moving from position " + (currentPosition + diceValue) + " to " + getBlackPortalEnd());
currentPosition = getBlackPortalEnd();
} else {
System.out.println("You landed on " + (currentPosition + diceValue));
currentPosition += diceValue;
}
}
}
So in my main method I call the it like create and call this class like;
WorldOfOz oz = new WorldOfOz();
oz.go.builder(30)
.dice(1, 4)
.whitePortal(5, 12)
.blackPortal(13, 2)
.build();
My issue is when I want to add in more than 1 whitePortal/blackPortal
WorldOfOz oz = new WorldOfOz();
oz.go.builder(30)
.dice(1, 4)
.whitePortal(5, 12)
.whitePortal(18, 26)
.blackPortal(13, 2)
.build();
The values 18 - 26 override 5 - 12. How can I set this up so I can have multiple white and black portals?
It seems that your data structure is not enough to solve this problem.
You need to define a collection of whitePortals and a collection of blackPortals. If you do so calling the method whitePortal(5, 12) add a new white portal insted of setting the white portal values of the only white existing portal.
You need to define a class Portal
public class Portal {
private int portalStart;
private int portalEnd;
...
public Portal(int s, int e) {
this.portalStart = s;
this.portalEnd = e;
}
}
Then you can use it in the GameObject as follow:
public GameObject {
List<Portal> whitePortals;
List<Portal> blackPortals;
public GameObject() {
whitePortals = new ArrayList<Portal>();
blackPortals = new ArrayList<Portal>();
}
public GameObject addWhitePortal(int m, int o) throws Exception {
whitePortals.add(new Portal(m, o));
return this;
}
...
// You need to change other methods to follow a different data structure
}
Well, you can use the following approach:
Introduce a new "Portal" type with start/end attributes
Replace white/black portal attributes in your class with lists for white and black portals (or any other type of collection you like)
Replace getWhite/Black methods with access to lists
Refactor whitePortal and blackPortal method to create new instances of a portal object and add them to an appropriate collection
You can, of course, use arrays instead of collections, but that's a bit more cumbersome.
Also, assuming portals are collections, you probably need to add helper methods for operating on those. Depending on what your actual needs are.
public class Portal
{
private int start;
private int end;
public Portal(int start, int end) { ... }
public getStart() {...}
public getEnd() {...}
public setStart(int end) {...}
public setEnd(int start) {...}
}
public class GameObject
{
...
private List<Portal> whitePortals = new ArrayList<Portal>();
private List<Portal> blackPortals = new ArrayList<Portal>();
...
public GameObject whitePortal(int m, int o) throws Exception {
whitePortals.add(new Portal(m, o));
return this;
}
public GameObject blackPortal(int o, int m) throws Exception {
blackPortals.add(new Portal(m, o));
return this;
}
...
}
I tried looking up tutorials and videos and I understand what implementing does, although I'm a bit confused as to how one would implement a class from the Java Library. In my homework, I'm suppose to utilize the class, DataSet and make it so it accepts Comparable objects. The program is suppose to record the Min and Max values depending on the objects, in this case, I'm suppose to use strings. I wasn't sure if I needed any classes to implement the Comparable interface, so I made two classes just in case I was suppose to do so. My real question is how do I actually incorperate a String variable in the tester class to actually read and compare the object to another? thanks in advance.
public class Word implements Comparable
{
private String str;
public Word()
{
str = null;
}
public Word(String s)
{
str = s;
}
public int compareTo(Object other)
{
String n = (String) other;
return str.compareTo(n);
}
}
I wasn't sure which of the two classes would be suitable for implementing Although i think the String class below would not work at all b/c It's already a standard class so I wasn't too sure about using it
public class String implements Comparable
{
public String s;
public String()
{
s = null;
}
public String(String str)
{
s = str;
}
public int compareTo(Object other)
{
String n = (String) other;
return s.compareTo(n);
}
}
public interface Comparable
{
public int compareTo(Object other);
}
public class DataSet
{
private Object maximum;
private Object least;
private Comparable compare;
private int count;
public DataSet(Comparable s)
{
compare = s;
}
public void add(Object x)
{
if(count == 0)
least = x;
if(count == 0 || compare.compareTo(x) >=0)
maximum = x;
else if(compare.compareTo(x) <0)
least = x;
count++;
}
public Object getMaximum()
{
return maximum;
}
public Object getLeast()
{
return least;
}
}
public class DataSetTester
{
public static void main(String[] args)
{
Comparable n = new Word("sand");
DataSet data = new DataSet(n);
data.add(new Word(man));
System.out.println("Maximum Word: " + data.getMaximum());
System.out.println("Least Word: " + data.getLeast());
}
}
An interface is a contract that showes that your class contain all methodes that are implemented in the interface. In this case the CompareTo(object other). The String class already implements the comparable interface so you don't need youre own class. I think your data set class should look something like this :
public class DataSet<T implements Comparable>
{
private T maximum;
private T least;
private T count;
public void add(T x)
{
if(count == 0){
least = x;
maximum = x;
}
else if(least.compareTo(x) > 0)
least = x;
else if(maximum.compareTo(x) < 0)
maximum = x;
count++;
}
public T getMaximum()
{
return maximum;
}
public T getLeast()
{
return least;
}
}
T is a generic type and in your case it should be String, Here is how you create a new Data set:
DataSet<String> ds = new DataSet<String>;
I have the following code for sorting. Can this be improved?
import java.util.*;
class Church {
private String name;
private String pastor;
public Church(String name, String pastor) {
this.name = name;
this.pastor = pastor;
}
public String getPastor() {
return pastor;
}
public String getName() {
return name;
}
public void setPastor(String pastor) {
this.pastor = pastor;
}
public String toString() {
return getName() + " is Pastored by "+getPastor();
}
public int compareByPastor(Church c) {
int x = pastor.compareTo(c.getPastor());
return x;
}
public int compareByName(Church c) {
int x = name.compareTo(c.getName());
return x;
}
}
class Churches {
private final List<Church> churches;
public Churches() {
churches = new ArrayList<Church>();
}
public void addWithoutSorting(Church c) {
churches.add(c);
}
//You could always add using this method
public void addWithSorting(Church c) {
}
public void display() {
for(int j = 0; j < churches.size(); j++) {
System.out.print(churches.get(j).toString());
System.out.println("");
}
}
public List<Church> getChurches() {
return churches;
}
public void sortBy(String s) {
for (int i = 1; i < churches.size(); i++) {
int j;
Church val = churches.get(i);
for (j = i-1; j > -1; j--) {
Church temp = churches.get(j);
if(s.equals("Pastor")) {
if (temp.compareByPastor(val) <= 0) {
break;
}
}
else if(s.equals("Name")) {
if (temp.compareByName(val) <= 0) {
break;
}
}
churches.set(j+1, temp);
}
churches.set(j+1, val);
}
}
public static void main(String[] args) {
Churches baptists = new Churches();
baptists.addWithoutSorting(new Church("Pac", "Pastor G"));
baptists.addWithoutSorting(new Church("New Life", "Tudor"));
baptists.addWithoutSorting(new Church("My Church", "r035198x"));
baptists.addWithoutSorting(new Church("AFM", "Cathy"));
System.out.println("**********************Before Sorting***********************");
baptists.display();
baptists.sortBy("Pastor");
System.out.println("**********************After sorting by Pastor**************");
baptists.display();
baptists.sortBy("Name");
System.out.println("**********************After sorting by Name****************");
baptists.display();
}
}
Take a look at Collections.sort(list, comparator)
http://download.oracle.com/javase/6/docs/api/java/util/Collections.html
class Churches
{
public void sortBy(String attribute)
{
Comparator<Church> c = null;
if ("Name".equals(attribute)) c = new ChurchNameComparator();
else if ("Pastor".equals(attribute)) c = new ChurchNameComparator();
else System.out.println("unexpected sort attribute : '" + attribute + "'");
if (c != null) Collections.sort(churches, c);
}
private static final class ChurchNameComparator implements Comparator<Church>
{
public int compare(Church c1, Church c2)
{
return c1.getName().compareTo(c2.getName());
}
}
private static final class ChurchPastorComparator implements Comparator<Church>
{
public int compare(Church c1, Church c2)
{
return c1.getPastor().compareTo(c2.getPastor());
}
}
}
The real answer here is pretty much in line with iluxa's: you want to implement a Comparator interface on your Church objects (sample code here, though you'll want to decide what constitutes greater than/less than for a church...), and then you can use Collections.sort() to sort them. That will get the job done, at the end of the day.
Of course, you just asked for advice about sorting on Stack Overflow, so I feel compelled to ask you if you need an in-place sort, what kind of Big-O performance you're looking for, and then ask you to choose between Quicksort, IntroSort, HeapSort, MergeSort, and StoogeSort for what will work best for you.
For kicks, I once coded up a few sorts in Java:
This one forces Quicksort into quadratic time, which was harder to do than I'd originally assumed,
This one shows how to implement MergeSort,
and this one demonstrates a HeapSort
I did these for my own enjoyment and education. As a general rule, you want to stick with the standard library for these sorts of things.