I don't know why my list is not sorted.
I'm using Collection.sort, it seems to do the job but when I launch the UnitTest it outputs an error.
Expected :characterWithMaxVotes [voteCount : 100]
Actual :characterMiddle75[voteCount : 75]
//Exact same method as in the Character class (pasted for better readability on SO question)
public static void sortCharactersByVotes(List<Character> lstCharacters) {
Collections.sort(lstCharacters, new Comparator<Character>() {
#Override
public int compare(Character character, Character p1) {
int result = (character.getVoteCount() > p1.getVoteCount()) ? 1 : 0;
return result;
}
});
}
#Test
public void sortCharactersByVoteCounts() {
Character characterWithMinVotes = Character.newBuilder().name("characterWithMinVotes").voteCount(0).build();
Character characterMiddle25 = Character.newBuilder().name("characterMiddle25").voteCount(25).build();
Character characterMiddle75 = Character.newBuilder().name("characterMiddle75").voteCount(75).build();
Character characterWithMaxVotes = Character.newBuilder().name("characterWithMaxVotes").voteCount(100).build();
List<Character> lstCharacters = new ArrayList<>();
lstCharacters.add(characterMiddle75);
lstCharacters.add(characterWithMaxVotes );
lstCharacters.add(characterMiddle25);
lstCharacters.add(characterWithMinVotes);
sortCharactersByVotes(lstCharacters);
System.out.print(lstCharacters);
assertEquals(lstCharacters.get(0), characterWithMaxVotes);
assertEquals(lstCharacters.get(1), characterMiddle75);
assertEquals(lstCharacters.get(2), characterMiddle25);
assertEquals(lstCharacters.get(3), characterWithMinVotes);
}
How to do it properly, thank you for your help.
PS : as requested, here is my Character class
public class Character {
private static final String TAG = "Character";
private int id;
private String name = "";
public int voteCount;
public boolean isVotedByUser = false;
public int getId() {
return id;
}
public int getVoteCount() {
return voteCount;
}
public String getName() {
return name;
}
public static CharacterBuilder newBuilder(){
return new CharacterBuilder();
}
#Override
public String toString() {
return name + "[voteCount : " + voteCount + "]";
}
public static void sortCharactersByVotes(List<Character> lstCharacters) {
Collections.sort(lstCharacters, new Comparator<Character>() {
#Override
public int compare(Character character, Character p1) {
int result = (character.getVoteCount() > p1.getVoteCount()) ? 1 : 0;
return result;
}
});
}
public static class CharacterBuilder {
public Character character;
CharacterBuilder() {
character = new Character();
}
public CharacterBuilder id(int id) {
character.id = id;
return this;
}
public CharacterBuilder name(String name) {
character.name = name;
return this;
}
public CharacterBuilder voteCount(int voteCount) {
character.voteCount = voteCount;
return this;
}
public Character build() {
return character;
}
}
}
(edited to use Integer.compare as suggested)
The compare method must return 0 if and only if the two compared objects have equal "rank" (in your case, equal vote count), otherwise must return a positive value if a>b or negative if b>a (or vice versa, according to the wanted sort direction).
To solve this simply, you can write (assuming getVoteCount() is int):
public int compare(Character character, Character p1) {
return Integer.compare(p1.getVoteCount(), character.getVoteCount());
}
(to reverse the sort result, just swap the operands)
The implementation of your Comparator is not correct, as you want to have highest value first (and not the opposite lowest value first), you are supposed to return a positive value if character.getVoteCount() < p1.getVoteCount() and a negative value if character.getVoteCount() > p1.getVoteCount(), you should use Integer.compare(int x, int y) to compare the values of getVoteCount() (assuming that it returns an int) such that your Comparator could be :
new Comparator<Character>() {
#Override
public int compare(Character c1, Character c2) {
return Integer.compare(c2.getVoteCount(), c1.getVoteCount());
}
}
NB: Don't compare the values of getVoteCount() with a simple subtraction otherwise you will take the risk to get incorrect results as it is prone to overflow issues.
I think that is better to change a little bit the comparator implemented. Try:
public static void sortCharactersByVotes(List<Character> lstCharacters) {
Collections.sort(lstCharacters, new Comparator<Character>() {
#Override
public int compare(Character character, Character p1) {
int result = (character.getVoteCount() - p1.getVoteCount());
return result;
}
});
}
Another thing is that you are adding twice the
characterWithMaxVotes
Hope it helps!
You sort of comparison method shall be modified to
public static void sortCharactersByVotes(List<Character> lstCharacters) {
lstCharacters.sort(Comparator.comparingInt(Character::getVoteCount));
}
Note - The comparison is based on the integer getVoteCount of Character and this is supported in Java 8+.
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 coding something for a theoretical airport case study and I need help with one bit. I've got 2 different integers with names: maxfuelCapacity and fuelCurrent, and I need something that says ' fuel needed to pump is '.....' being the difference between the maxfuelCapacity of the plane and the current amount. There are no real values so far. How do I go about doing that?
public static int maxfuelCapacity;
public int fuelCurrent;
public String name;
Boolean parked;
public String[] Plane = {
"BA103", "BA493", "BA209"
};
public void setName(String n) {
name = n;
}
public void setParked(Boolean o) {
parked = o;
}
public int getInt(String Maxfuelcapacity) {
return maxfuelCapacity;
}
public String getInt1 (String fuelCurrent) {
return fuelCurrent;
}
As has been mentioned in the comments, your method would look like:
public int fuelNeeded(int fuelCurrent, int maxfuelCapacity) {
if(fuelCurrent >= maxfuelCapacity) {
System.out.println("The tank already has enough");
return 0;
}
return maxfuelCapacity- fuelCurrent;
}
So you call this method in your main function that does the calculation.
I have three integer values along with its text. My requirement is to give rank to all of them.
E.g. I have A = 50 points, B = 500 Points, C = 50 points.
Now I would like to compare all of these and find max and equal values and its according name(like, A/B/C).
EDIT ::
As a output it should return, B = 1st Rank, A = 2nd Rank, C = 2nd Rank.
If anyone has any idea about how can I implement code as per my requirement then, it would be great.
Thanks in advance.
public class ScoreVO implements Comparator<Integer> {
private String playerName = Constants.BLANK_STRING;
private int playerScore;
public String getPlayerName () {
return playerName;
}
public void setPlayerName ( String playerName ) {
this.playerName = playerName;
}
public int getPlayerScore () {
return playerScore;
}
public void setPlayerScore ( int playerScore ) {
this.playerScore = playerScore;
}
#Override
public int compare ( Integer o1, Integer o2 ) {
return o2.compareTo ( o1 );
}
}
Here is my class with Comparator<>.
Please suggest me if I am wrong.
A sample running code which gives output shown below as per your requirement along with player rank. There is a separate method assignRank(List<>) which you can use to assign ranks to players.
Score List: [ScoreVO [playerName=B, playerScore=500, playerRank=1], ScoreVO [playerName=A, playerScore=50, playerRank=2], ScoreVO [playerName=C, playerScore=50, playerRank=2]]
public class ScoreExample {
public static void main(String[] args) {
List<ScoreVO> scoreList = new ArrayList<ScoreVO>();
scoreList.add(new ScoreVO("A", 50));
scoreList.add(new ScoreVO("C", 50));
scoreList.add(new ScoreVO("B", 500));
Collections.sort(scoreList);
assignRank(scoreList);
System.out.println("Score List: "+scoreList);
}
private static void assignRank(List<ScoreVO> scoreList) {
int rank = 0;
int score = 0;
for(ScoreVO scoreVO : scoreList) {
if(score != scoreVO.getPlayerScore()) {
rank++;
scoreVO.setPlayerRank(rank);
score = scoreVO.getPlayerScore();
} else {
scoreVO.setPlayerRank(rank);
}
}
}
}
class ScoreVO implements Comparable<ScoreVO> {
public String playerName;
public int playerScore;
public int playerRank;
public ScoreVO(String playerName, int playerScore) {
this.playerName = playerName;
this.playerScore = playerScore;
}
public String getPlayerName() {
return playerName;
}
public void setPlayerName(String playerName) {
this.playerName = playerName;
}
public int getPlayerScore() {
return playerScore;
}
public void setPlayerScore(int playerScore) {
this.playerScore = playerScore;
}
public int getPlayerRank() {
return playerRank;
}
public void setPlayerRank(int playerRank) {
this.playerRank = playerRank;
}
#Override
public int compareTo(ScoreVO o) {
if(o.getPlayerScore() != getPlayerScore()) {
if(getPlayerScore() > o.getPlayerScore())
return -1;
else
return 1;
}
return getPlayerName().compareTo(o.getPlayerName());
}
#Override
public String toString() {
return "ScoreVO [playerName=" + playerName + ", playerScore="
+ playerScore + ", playerRank=" + playerRank + "]";
}
}
ScoreVO should implement Comparable<ScoreVO>. And your compareTo method looks like this:
#Override
public int compareTo ( ScoreVO o ) {
if(playerScore != o.playerScore)
return Integer.compare(playerScore, o.playerScore);
return playerName.compareTo(o.playerName);
}
You should implment Comparable for ordering purpuses, and equals() for equation (that can use compareTo)
like this
public class ScoreVO implements Comparable<ScoreVO> {
#Override
public int compareTo(ScoreVO other) {
return other == null ? 1 : getPlayerScore() - other.getPlayerScore();
}
#Override
public boolean equals(object other) {
return !(other instanceof ScoreVO) ? false : compareTo(other) == 0 ;
}
}
However, you probably want to compare equality based on player name. think of putting ScoreVO object in a map - what is the key? so -
#Override
public boolean equals(object other) {
return other == null || !(other instanceof ScoreVO) ? false :
getPlayerName.equals(other.getPlayerName()) ;
}
As there are just three values, it is possible to hard-code all operations. You can think of a very compact and efficient way to work this out.
Every comparison of two values can give an outcome >, = or <. Assigning the value 0, 1 or 2 to these, you can pack the three comparisons in a single number using base 3 encoding. You will end up with a number in range 0 to 26, and every different value corresponds to a different answer that you can tabulate (or process in a switch statement).
int Compare(int A, int B) { return A > B ? 0 : (A == B ? 1 : 2); }
char* Answer[27]= { "A1B2C3", "A1B1C3", "B1A2C3", ... }; // To be filled
return Answer[Compare(A, B) + 3 * compare(B, C) + 9 * compare(A, C)];
I am using three classes in my program:
Term class with variables coefficient and exponent, toString() method etc.
Polynome class, using an ArrayList to store the different Term objects.
Main class that runs the program.
Can I use the toString method of ArrayList in my Polynome class? I'm trying to, but I can't.
I need my polynome to output like this: [3x^2, 3x^1, 1x^0]
I am really confused, I'm calling the toString method of Term, using a for-loop to access each term separately.
My code:
public class Term {
private int coëfficiënt;
private int exponent;
public Term(int coëfficiënt, int exponent) {
this.coëfficiënt = coëfficiënt;
this.exponent = exponent;
}
public int getCoef() {
return coëfficiënt;
}
public int getExp() {
return exponent;
}
public String toString() {
return coëfficiënt + "x^" + exponent;
}
}
Polynome class:
public class Polynoom {
private ArrayList<Term> polynoom;
public Polynoom() {
polynoom = new ArrayList<Term>();
}
public void add(Term term) {
polynoom.add(term);
}
public Term get(int i) {
return polynoom.get(i);
}
public int size() {
return polynoom.size();
}
public String toString() {
// what should I write here?
}
}
Main class:
public class opgave3 {
public static void main(String[] args) {
Polynoom polynoom1, polynoom2, sompolynoom;
polynoom1 = new Polynoom();
polynoom1.add(new Term(1, 2));
polynoom1.add(new Term(3, 1));
polynoom1.add(new Term(1, 0));
polynoom2 = new Polynoom();
polynoom2.add(new Term(-1, 3));
polynoom2.add(new Term(2, 2));
polynoom2.add(new Term(-5, 0));
System.out.println("Tests: ");
System.out.println(polynoom1.toString());
for (int i = 0; i < polynoom1.size(); i++) {
System.out.println(polynoom1.get(i).toString());
}
System.out.println(polynoom1.get(0).toString());
}
}
You just need to use your ArrayList's toString() method as the results of Polynome's toString() method.
public class Polynome {
public ArrayList<Term> terms;
#Override
public String toString() {
if (terms != null) {
return terms.toString();
} else {
return "";
}
}
}
EDIT: The quick answer, since you put your code up is to put
return polynoom.toString();
where you have indicated. Then in your Main class you can simply write
System.out.println(polynoom1);
to show the contents in the desired format.
As Tenner said, use the toString() method of your ArrayList to get the desired output. But also make sure your Term class has a useful toString method of its own:
public class Term {
private int co, ex;
public Term(int coeff, int exp) {
co = coeff;
ex = exp;
}
#Override
public String toString() {
return co + "x^" + ex;
}
}
Add #Override toString() to your Term & Polynome class. The Term class toString() should return a string in the format of coefficientx^exponent.
Then have the Polynome class toString() return yourArrayList.toString()
public static void main(String[] args) throws Exception {
Polynome polynome = new Polynome();
polynome.addTerm(3, 2);
polynome.addTerm(3, 1);
polynome.addTerm(1, 0);
System.out.println(polynome);
}
public static class Term {
private int coefficient;
private int exponent;
public Term(int c, int e) {
coefficient = c;
exponent = e;
}
#Override
public String toString() {
return coefficient + "x^" + exponent;
}
}
public static class Polynome {
private List<Term> terms = new ArrayList<>();
public void addTerm(int coefficient, int exponent) {
terms.add(new Term(coefficient, exponent));
}
#Override
public String toString() {
return terms.toString();
}
}
Results:
Long story short, you can ALWAYS use toString() on anything, even if it's a user defined class. When you call the method, it calls the closest parent class's toString() method, which is guaranteed to be there as Object has one. If you want to control the output of toString() called on your object, you must override it. As it is, if you have an object with a member of type ArrayList, calling your object's toString() will include a ton of extra information that you probably don't want. In order to get the output you want, you need to have the code given by #Tenner's answer, which is
public class Polynome {
public ArrayList<Term> terms;
#Override
public String toString() {
if (terms != null) {
return terms.toString();
} else {
return "";
}
}
}
But you also need to override toString() in the Term class, so that each term outputs in the form desired. The reason this is required is that when you call toString() on an ArrayList, or any other container for that matter, it iterates through the container, calling each object's toString() in turn, adding whatever formatting the container class defines. Ultimately, Term's toString() will be called, and you can control that output by overriding it in the Term class.
As for the last part of the question, you need not call Term's toString() directly, as calling the toString() method of the ArrayList will do this on its own.
I'm curious. What could be the reason that a Comparator shuffles entries on each
application start?
final static class ContactsListComparator implements Comparator
{
public int compare(Object o1, Object o2)
{
if((o1.toString().compareTo(o2.toString()))<0)
{
return -1;
}
if((o1.toString().compareTo(o2.toString()))>0)
{
return 1;
}
else
{
return 0;
}
}
}
First App Start:
Second App Start
As mentioned in one the answer
The Comparator actually compares an custom object Contact
public class Contact
{
// Members
private String _contactFirstName;
private String _contactLastName;
private long _contactLastModified;
// Constructor
public Contact()
{
set_contactLastModified();
}
public Contact(String contactFirstName)
{
_contactFirstName = contactFirstName;
set_contactLastModified();
}
// Accessable Getters
public String get_contactFirstName()
{
return _contactFirstName;
}
public String get_contactLastName()
{
return _contactLastName;
}
public long get_contactLastModified()
{
return _contactLastModified;
}
public void set_contactLastModified()
{
_contactLastModified = System.currentTimeMillis();
}
}
your toString method probably isn't overridden for your objects representing the contacts. It will return a hash string for those objects, which varies every time your app is run.
You can fix this either of two ways:
Override the toString() method in your Contact object to return the contact's name (1), or
Change the Comparator to Comparator<Contact> so it gets Contact objects as parameters (2)
for (1), add this to your Contact class:
#Override public String toString() {
return get_contactFirstName();
}
for (2) you would end up with this Comparator implementation:
final static class ContactsListComparator implements Comparator<Contact> {
public int compare(Contact o1, Contact o2) {
return contact1.get_contactFirstName().compareTo(contact2.get_contactFirstName());
}
}
you don't even need to check for the <0 or >0, but you can just return whatever the String comparison gives.
I would use:
final static class ContactsListComparator implements Comparator<Contact>
{
public int compare(Contact c1,Contact c2)
{
int i=c1.get_contactLastName().compareTo(c2.get_contactLastName());
if(i!=0) return i;
return c1.get_contactFirstName().compareTo(c2.get_contactFirstName());;
}
}
Your first example is basically the same as
final static class ContactsListComparator implements Comparator {
public int compare(Object o1, Object o2) {
return o1.toString().compareTo(o2.toString());
}
}
This would work if you override toString() like
public String toString() {
return _contactFirstName + ' ' + _contactLastName;
}
However, a comparator which compares the intended fields is better as has been suggested.