Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 7 years ago.
Improve this question
public class Variable implements Comparable<Variable> {
String name;
String type;
public Variable(String name, String type){
this.name = name;
this.type = type;
}
public String getName(){
return name;
}
public String getType(){
return type;
}
public boolean equals(Object o){
if(o != null && (o instanceof Variable)) {
return ((Variable)o).getName().equals(name) &&
((Variable)o).getType().equals(type);
}
return false;
}
public int compareTo(Variable v){
if (type.compareTo(v.type) != 0) return type.compareTo(v.type);
return name.compareTo(v.name);
}
public String toString(){
return type+" "+name;
}
}
public class Operation implements Comparable<Operation>{
String name;
String type;
List<Variable> arguments;
public Operation(String name, String type){
this.name = name;
this.type = type;
arguments = new ArrayList<Variable>();
}
public void addArgument(Variable a){
arguments.add(a);
}
public String getName(){
return name;
}
public String getType(){
return type;
}
public List<Variable> getArguments(){
return arguments;
}
public int getArgumentNumber(){
return arguments.size();
}
public boolean equals(Object o){
if(o != null && (o instanceof Operation)) {
List<Variable> oa = ((Operation)o).getArguments();
Collection.sort(arguments);
Collection.sort(oa);
return ((Operation)o).getName().equals(name) &&
((Operation)o).getType().equals(type) &&
((Operation)o).getArguments().equals(arguments);
}
return false;
}
public int compareTo(Operation v){
if (type.compareTo(v.type) != 0) return type.compareTo(v.type);
else if(name.compareTo(v.name) != 0) return name.compareTo(v.name);
else{
if (arguments.size() < v.getArgumentNumber()) return -1;
else if(arguments.size() > v.getArgumentNumber()) return 1;
else
}
}
public String toString(){
String s = "";
if (arguments.isEmpty()) return type + " " + name + "(" + ")";
else {
for(Variable v:arguments){
s+= v.type + " ";
}
}
return type + " " + name + "(" + s.trim() + ")";
}
}
As you can see, in the equals function of Operation class
public boolean equals(Object o){
if(o != null && (o instanceof Operation)) {
List<Variable> oa = ((Operation)o).getArguments();
Collection.sort(arguments);
Collection.sort(oa);
return ((Operation)o).getName().equals(name) &&
((Operation)o).getType().equals(type) &&
((Operation)o).getArguments().equals(arguments);
}
return false;
}
I try to sort the list of Variable, but it give me error message "The method sort(List) is undefined for the type Collection", but I have already defined compareTo function in Variable class.
PS. anyone have idea that how should i define compareTo function in Operation class, should i sort first arguments and then compareTo each Variable?
Thanks.
You're using the wrong class to sort. Collection.sort does not exist, while Collections.sort does.
public boolean equals(Object o){
if(o != null && (o instanceof Operation)) {
List<Variable> oa = ((Operation)o).getArguments();
Collections.sort(arguments);
Collections.sort(oa);
return ((Operation)o).getName().equals(name) &&
((Operation)o).getType().equals(type) &&
((Operation)o).getArguments().equals(arguments);
}
return false;
}
Collections, as in plural, with an 's'.
http://docs.oracle.com/javase/8/docs/api/java/util/Collections.html#method.summary
PS. anyone have idea that how should i define compareTo function in
Operation class, should i sort first arguments and then compareTo each
Variable?
Since you rely on the order of arguments in your Operation class consider to store the Variables in arguments in a sorted order already.
This means eiter sort the List with every new added Variable or use a Set instead of the List. So you don't have to sort in your equals and compareTo methods.
To your question regarding the compareTo method:
if the size of arguments is the same iterate over both arguments lists comparing the same indices of the Variables via compareTo and return the first result which is != 0. (Or '0' if all elements are equal)
One possible solution:
public int compareTo(Operation v) {
int res = type.compareTo(v.type);
if (res != 0) return res;
res = name.compareTo(v.name);
if (res != 0) return res;
if (arguments.size() != v.arguments.size()) return arguments.size() - v.arguments.size();
for (int i = 0; i < arguments.size(); ++i) {
res = arguments.get(i).compareTo(v.arguments.get(i));
if (res != 0) return res;
}
return 0;
}
Related
I have a boolean method as following below
public boolean validID(String personalNumber) { .... }
I wanna to print out a string "is valid" or "is not valid" dependent on if the boolean true or false.
the problem is how can I print out string in a boolean method. The code below return always false even if the if statment is true.
if (sum % 10 == 0) {
return Boolean.parseBoolean("is valid");
} else {
return false;
}
You have only two choices :
a boolean method :
public boolean validID(String personalNumber) {
// ... code to compute 'sum'
return sum % 10 == 0;
}
a String method :
public String validID(String personalNumber) {
// ... code to compute 'sum'
if (sum % 10 == 0) {
return personalNumber + " is valid";
} else {
return personalNumber + " is not valid";
}
}
Or a choice that combine both, the String one that calls the boolean one :
public boolean isValidId(String personalNumber) {
// ... code to compute 'sum'
return sum % 10 == 0;
}
public String validID(String personalNumber) {
if (isValidId(personalNumber)) {
return personalNumber + " is valid";
} else {
return personalNumber + " is not valid";
}
}
I'd suggest to take the boolean one, the better is to let the method find the validity of the personalNumber and let the code that calls it handle the result to print a message, because you may this method again and this time you'll need the boolean result to handle it differently
String id = "fs6d7f6sd";
if(this.validID(id))
System.out.println("ID is valid");
else
System.out.println("ID is not valid");
I recommend to use bean Result.
Check my code.
class Result {
private boolean value;
private String message;
public Result(boolean value, String message) {
this.value = value;
this.message = message;
}
// getter & setter
}
public Result validID(String number) {
// ... code to compute 'sum'
return sum % 10 == 0 ?
new Result(true, "valid") :
new Result(false, "invalid");
}
I need to create a method that return the index of an object in a list by comparing one of its fields.
I have 2 classs A and B with overrided Equals() and HashCode() methods like this:
Class A:
public class A {
private String field1;
private String field2;
//getters and setters
#Override
public boolean equals (Object o){
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
if (!super.equals(o)) return false;
A that = (A) o;
return field1.equals(that.field1);
}
#Override
public int hashCode() {
int result = super.hashCode();
result = 31 * result + field1.hashCode();
return result;
}
}
Class B :
public class B {
private String field1;
private String field2;
//getters and setters
#Override
public boolean equals (Object o){
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
if (!super.equals(o)) return false;
B that = (B) o;
return field2.equals(that.field2);
}
#Override
public int hashCode() {
int result = super.hashCode();
result = 31 * result + field2.hashCode();
return result;
}
}
In my main program I need to implement a generic method that returns the index of an item within an ArrayList<> of A or B.
private int getObjectIndexFromList(List<A or B> list, A or B param){
int index;
try{
index = list.indexOf(list.stream().filter(e -> e.equals(param)));
}catch (NoSuchElementException ex){
index = -1;
}
return index;
}
So my question is how to pass generic params for the method ?
I'm assuming you want to compare with either A.field1, A.field2, B.field1, or B.field1?
In that case you can use a lambda to find it in the stream. Like this:
private <T> int getObjectIndexFromList(List<T> list, Predicate<T> predicate){
int index;
try {
index = list.indexOf(list.stream()
.filter(predicate)
.findFirst()
.get());
} catch (NoSuchElementException ex){
index = -1;
}
return index;
}
Then you just use it like this:
int index = getObjectIndexFromList(listOfAs, a -> a.field1.equals("foo"));
Using streams here isn't optimal though since you're effectively traversing the list twice and checking equality on both the parametar and the sought object. Using a list iterator that keeps track of the current index is be more efficient:
private <T> int getObjectIndexFromList(List<T> list, Predicate<T> predicate){
ListIterator<T> it = list.listIterator();
while (it.hasNext()) {
// Get the item and it's index in the list
int index = it.nextIndex();
T item = it.next();
if (predicate.test(item)) {
// We found it, return the index
return index;
}
}
// We didn't find anything
return -1;
}
Here's an example of it in use:
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("foo");
list.add("bar");
list.add("foobar");
list.add("fubar");
list.add("Hello World!");
System.out.printf("String with length %s has index %s%n",
5, getObjectIndexFromList(list, s -> s.length() == 5));
}
And the output:
String with length 5 has index 3
If you have override hashcode and equals methods... why don't you make a plain call to 'List.indexOf'?
Make them extend the same abstract class (I don't know the exact problem, but if they have end in the same List is highly probable that they will end being family) and use it.
IndexOf uses 'equals' to find the index of the object so it must work...
package restaurantclient;
public class Restaurant extends Store {
//Instance Variables
private int peopleServed;
private double averagePrice;
//Constructor with 3 parameters
public Restaurant(String storename, int peopleServed, double averagePrice) {
super(storename);
setPeopleServed(peopleServed);
setAveragePrice(averagePrice);
}
//Getters (Accessors)
public int getPeopleServed() {
return peopleServed;
}
public double getAveragePrice() {
return averagePrice;
}
//Setters (Mutators)
public void setPeopleServed(int peopleServed) {
this.peopleServed = peopleServed;
}
public void setAveragePrice(double averagePrice) {
this.averagePrice = averagePrice;
}
//toString Method [Must Override]
#Override
public String toString() {
String information = "Store name: " + (super.getName());
information += "\n" + "The number of people served: " + peopleServed;
information += "\n" + "The average price per person: $" + averagePrice;
return information;
}
//Equals Method
#Override
public boolean equals (Object other) {
if (this == other)
return true;
if (other == null)
return false;
if (!(other instanceof Restaurant))
return false;
Restaurant otherRestaurant = (Restaurant) other;
if (this.getName() == null) {
if (otherRestaurant.getName() != null)
return false;
} else if (!(this.getName().equals(otherRestaurant.getName())))
return false;
if (peopleServed == -1) {
if (otherRestaurant.peopleServed != -1)
return false;
} else if (peopleServed != (otherRestaurant.peopleServed))
return false;
if (averagePrice == -1) {
if (otherRestaurant.averagePrice != -1)
return false;
}
else if (averagePrice != (otherRestaurant.averagePrice))
return false;
return true;
}
public double getAverageTaxes() {
double total;
total = this.getPeopleServed() * this.getAveragePrice()
* super.CA_TAX_RATE;
return total;
}
}
package restaurantclient;
public class Store {
//Instance Variables
protected final double CA_TAX_RATE = 0.0884;
private String storename;
//Constructor
public Store(String storename) {
setName(storename);
}
//Getters (Accessors)
public String getName() {
return storename;
}
//Setters (Mutators)
public void setName(String storename) {
this.storename = storename;
}
//toString Method [Must Override]
#Override
public String toString() {
String directory = "Name of store: " + storename;
return directory;
}
//Equals Method
public boolean equals (Store storename) {
if (this == storename)
return true;
if (storename == null)
return false;
if (!(storename instanceof Store))
return false;
return true;
}
}
Above are the equals methods I'm calling. They are displaying the wrong answers: it should be in the first instance, "They are not equal" and in the second instance after setting everything equal to each other, it should display, "They are equal". I have tried very hard on this problem and many things have not worked. There are no overt errors it runs fine, but I am doing something wrong and some precise guidance would be a lot of help. Much of the vague hints have got me nowhere. I need something concrete, if this makes to you. Thanks again for the help. The following is the Client class:
package restaurantclient;
public class RestaurantClient {
public static void main(String[] args) {
Restaurant r1 = new Restaurant("McDonald's", 1000000, 8.00);
Restaurant r2 = new Restaurant("KFC", 500000, 6.00);
System.out.println(r1.toString());
System.out.println(r2.toString());
System.out.println();
r2.setAveragePrice(r1.getAveragePrice());
r2.setPeopleServed(r1.getPeopleServed());
System.out.println(r1.toString());
System.out.println(r2.toString());
if (r1.equals(r2)) {
System.out.println("The objects are equal.");
}
else {
System.out.println("The objects are not equal."); //SHOULD say "not equal" here EVERY TIME the second instance (next comment down) says "Equal"...this should never change.
System.out.println();
}
System.out.println();
r2.setName(r1.getName());
System.out.println(r1.toString());
System.out.println(r2.toString());
if (r1.equals(r2)) {
System.out.println("The objects are equal."); //Now that everything is equal, it should print "The Objects are Equal" but it doesn't. It's in lock-step with the previous instance. Changing some things like return true to return false might make both these instances "Are equal" and some might change them to "Not Equal" but they are never the way I want them, which is when 2 changes are made, they are not equal (first case) and when the third and final change is made (like this case here on this line) it should say "the obj are equal" but it doesn't.
}
else {
System.out.println("The objects are not equal.");
System.out.println();
}
System.out.println();
System.out.print("The avg. annual taxes paid by the restaurant is: $");
System.out.println(r1.getAverageTaxes());
}
}
The reason that I see is simple, you are not getting the same name.
In equals, you are comparing super.getName() with otherRestaurant.getName()
If the superclass of Restaurant have a different format or return an other variable, since you compare it to Restaurant.getName(), this will compare different value. Using this.getName() to compare the same variable (or format of variable) is safer. Even if Restaurant.getName() is only returning the super.getName(), this would be safer if you changed the method of Restaurant (because you prefer it an other way).
Here is an example :
Restaurant:
public String getName(){
return "A restaurant " + name;
}
Super class :
public String getName(){
return name;
}
Will result into comparing "A restaurant : KFC" with "KFV".
Using the same getter assure you to return the same "format".
Aslo, your logic is wrong. You want to check if one of the value is different, if it is, return false. And if you reach the end of the method, meaning there where no difference leading to a return false, you return true.
if (this.getName() == null) {
if (otherRestaurant.getName() != null)
return false;
} else if (!super.getName().equals(otherRestaurant.getName())) // added ! here
return false;
if (peopleServed == -1) {
if (otherRestaurant.peopleServed != -1)
return false;
} else if (peopleServed != (otherRestaurant.peopleServed)) // change to != here
return false;
if (averagePrice == -1) {
if (otherRestaurant.averagePrice != -1)
return false;
}
else if (averagePrice != (otherRestaurant.averagePrice)) // change to != here
return false;
//No differences, then it is equals.
return true;
Note :
This condition could be shorten
if (averagePrice == -1) {
if (otherRestaurant.averagePrice != -1)
return false;
}
else if (averagePrice != (otherRestaurant.averagePrice)) // change to != here
return false;
Since it is doing the same thing (comparing the values) :
if (averagePrice != (otherRestaurant.averagePrice))
return false;
Edit :
You are having a problem of overriding.
In Store:
public boolean equals(Store s){}
And in Restaurant
public boolean equals(Object o){}
Since you are calling the method with a Restaurant (subclass of Store), the JVM will use the Store.equals method since it match the type, Restaurant.equals is not overriding it, it override the method in Object. Change to Store.equals(Object o) to correct this.
The method equals comes from Object so it should be always receiving an Object to prevent any problem like this one, if you specify the type in a method, it will not override correctly the method (depending on the type)
Seems you are checking for equality and then returning false, when you should check for not equality to return false.
else if (!super.getName().equals(otherRestaurant.getName()))
return false;
else if (peopleServed != (otherRestaurant.peopleServed))
return false;
else if (averagePrice != (otherRestaurant.averagePrice))
return false;
Also as asked, any reason to uses super.getName() ?
And since peopleServed & averagePrice cannot be null, the -1 check is not needed as the expected result we be the same as the equality check
And finally, I'm guessing the end return should be true, as it means it's different instance of an object, but they have all the same attributs.
Within your equals() method , If super.name() equals otherRestaurant.name() shouldn't you return true, here:
else if (super.getName().equals(otherRestaurant.getName())) return false;
Ok, that one will work in any cases:
#Override
public boolean equals (Object other) {
if (this == other)
return true;
if (other == null)
return false;
if (!(other instanceof Restaurant))
return false;
Restaurant otherRestaurant = (Restaurant) other;
if (name == null) {
if (otherRestaurant.getName() != null)
return false;
} else if (name!=otherRestaurant.getName())
return false;
if (peopleServed == -1) {
if (otherRestaurant.peopleServed != -1)
return false;
} else if (peopleServed != otherRestaurant.peopleServed)
return false;
if (averagePrice == -1) {
if (otherRestaurant.averagePrice != -1)
return false;
}
else if (averagePrice != otherRestaurant.averagePrice)
return false;
return true;
}
check it and reply if it is ok
I implemented the equal’s method in my Person object with the #annotation, however, when I create an object in my main class and check it against my List of Person objects, it doesn’t return the correct index. It says they are both at 1, but it should be 1 and 3.
Objective:
Check to see if “Andy Bernard” exists in my list and if so, display the index of the objects.
import java.util.ArrayList;
import java.util.List;
public class Person {
private String firstName;
private String lastName;
public Person(String firstName,String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
#Override
public String toString() {
return String.format(this.firstName + " " + this.lastName);
}
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result
+ ((firstName == null) ? 0 : firstName.hashCode());
result = prime * result
+ ((lastName == null) ? 0 : lastName.hashCode());
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Person other = (Person) obj;
if (firstName == null) {
if (other.firstName != null)
return false;
} else if (!firstName.equals(other.firstName))
return false;
if (lastName == null) {
if (other.lastName != null)
return false;
} else if (!lastName.equals(other.lastName))
return false;
return true;
}
private static List<Person> deletePeople = new ArrayList<>();
public static void main(String[] args) {
addPerson("Micheal","Scott");
addPerson("Andy","Bernard");
addPerson("Micheal","Scott");
addPerson("Andy","Bernard");
display();
}
public static void addPerson(String firstname, String lastname) {
Person createPerson = new Person(firstname,lastname);
deletePeople.add(createPerson);
}
public static void display() {
Person checkPerson = new Person("Andy","Bernard");
for (Person display : deletePeople) {
if(display.equals(checkPerson)) {
System.out.println((display.getFirstName() + " " +
display.getLastName() + " " + deletePeople.indexOf(display)));
}
}
}
}
indexOf returns the index of the first occurence which is the same (according to the equals method) in the List. That's why you see both 1 printed.
Returns the index of the first occurrence of the specified element in
this list, or -1 if this list does not contain the element. More
formally, returns the lowest index i such that (o==null ? get(i)==null
: o.equals(get(i))), or -1 if there is no such index.
And you can see the implementation (for ArrayList, but that's the same idea for a LinkedList except that you iterate other the nodes):
229 public int indexOf(Object o) {
230 if (o == null) {
231 for (int i = 0; i < size; i++)
232 if (elementData[i]==null)
233 return i;
234 } else {
235 for (int i = 0; i < size; i++)
236 if (o.equals(elementData[i]))
237 return i;
238 }
239 return -1;
240 }
If you want to print the index associated, you can use a counter that you increment at each iteration.
int index = 0;
for (Person display : deletePeople) {
if(display.equals(checkPerson)){
System.out.println((display.getFirstName() + " " + display.getLastName() + " " + index));
}
index++;
}
It would also be possible with a standard for loop.
for(int i = 0; i < deletePeople.size(); i++){
Person display = deletePeople.get(i);
if(display.equals(checkPerson)){
System.out.println((display.getFirstName() + " " + display.getLastName() + " " + i));
}
}
However be careful with the latter implementation because if the underlying representation of the list is a LinkedList the complexity of the above loop would be O(n^2) instead of O(n).
By calling indexOf() you print the first index that matches, rather than the current index. If you're interested in tracking your position in the list, the best thing is to do that manually, so instead of a for-each loop:
for(Object o : ls) {
// the syntax is nice, but we don't have an easy way to
// tell how far into the list we are
System.out.println(o);
}
Instead, use a simple for loop:
for(int i = 0; i < ls.size(); i++) {
Object o = ls.get(i);
// Now we have access to the object *and* its index
System.out.println(i+": "+o);
}
Additionally, there's quite a few simple cleanups you could make in your code, if you'll forgive me, here's some suggestions:
Avoid allowing null in your objects - rarely is null actually meaningful, and allowing it forces all calling code to do null checks everywhere.
public Person(String firstName,String lastName) {
if(firstName == null || lastName == null) {
throw new NullPointerException("First/Last name cannot be null");
}
this.firstName = firstName;
this.lastName = lastName;
}
Use String.format() correctly, or just avoid it. Your current toString() method calls String.format(this.firstName + " " + this.lastName), which doesn't actually do anything; you might as well just return the concatenated string without String.format(). Alternatively, you can properly use the format functionality like so:
String.format("%s %s", firstName, lastName);
Take advantage of Java 7's Objects class for your hashCode() and equals() methods:
#Override
public int hashCode() {
return Objects.hash(firstName, lastName);
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Person other = (Person) obj;
return Objects.equals(firstName, other.firstName) &&
Objects.equals(lastName, other.lastName);
}
I am having a java class Rec. I have two instance of it Rec1 and Rec2. I want to check whether the values of Rec1 and Rec2 are equal. If i do Rec1.equals(Rec2) is it correct way of doing it?
class Rec {
private BigDecimal RecordId = null;
private BigDecimal recSubNum = null;
private BigDecimal FileId = null;
private String Category = null;
private BigDecimal status = null;
private BigDecimal errorCode = null;
}
You need to implement the equals() and hashCode() methods to implement object equality in Java:
class Rec {
private BigDecimal recordId = null;
private BigDecimal recSubNum = null;
private BigDecimal FileId = null;
private String category = null;
private BigDecimal status = null;
private BigDecimal errorCode = null;
#Override
public int hashCode() {
int ret = 41;
ret = hc(ret, recordId);
ret = hc(ret, recSubNum);
ret = hc(ret, fieldId);
ret = hc(ret, category);
ret = hc(ret, status);
ret = hc(ret, errorCode);
return ret;
}
#Override
public boolean equals(Object ob) {
if (ob == null) return false;
if (ob.getClass() != Rec.class) return false;
Rec r = (Rec)ob;
if (!eq(r.recordId, record)) return false;
if (!eq(r.recSubNum, recSubNum)) return false;
if (!eq(r.fileId, fileId)) return false;
if (!eq(r.category, category)) return false;
if (!eq(r.status, status)) return false;
if (!eq(r.errorCode, errorCode)) return false;
return true;
}
private static boolean eq(Object ob1, Object ob2) {
return ob1 == null ? ob2 == null : ob1.equals(ob2);
}
private static int hc(int hc, Object field) {
return field == null ? hc : 43 + hc * field.hashCode();
}
}
Note: the equals/hashCode contract for Java means that for any two objects a and b:
a.equals(b) == b.equals(a)
and if two objects are equal then a.hashCode() must equal b.hashCode().
Edit: there are two ways of checking if the types match. Either:
if (ob == null) return false;
if (ob.getClass() != Rec.class) return false;
or
if (!(ob instanceof Rec)) return false;
These two do different things and you should select the correct one depending on what you want to do. I generally prefer the first one unless you know you need the second. What's the difference?
class A {
public int i;
public boolean equals(Object ob) {
if (!(ob instanceof A)) return false;
return i == ((A)ob).i;
}
}
Looks reasonable right? What if the class gets extended:
class B extends A {
public int j;
public boolean equals(Object ob) {
if (!(ob instanceof B)) return false;
if (!super.equals(ob)) return false;
return j == ((B)ob).j;
}
}
Still looks reasonable? It's broken.
A a = new A();
a.i = 10;
B b = new B();
b.i = 10;
b.j = 20;
System.out.println(a.equals(b)); // true! Is this really what you want?
System.out.println(b.equals(a)); // false! Different to previous = problem.
That's why I favour getClass() over instanceof unless I really want subclass equality.
if Rec is a user defined class then you really should override the equals method otherwise it will just call the equals method in the Object class;
something like :
public boolean equals(Rec x){
//check here to see if the references are the same, if so return true
if(this == x) return true;
//if they aren't the same object then check all the fields for equality
if (category.equals(x.category) && etc etc) return true;
else return false;
}