override .equals() on a customer object [closed] - java

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 9 years ago.
Improve this question
I want to override equals on a custom object and want to check whether the current object is equal to the one passed in the parameter by Id (getId). How can I do that? Thanks

It's very difficult to give you an answer with only the information you've provided. But you want something roughly like this:
#Override
public boolean equals(Object o) {
if (! (o instanceof MyClass)) return false;
return id == ((MyClass)o).getId();
}
Where id is your data field (presumably an int) and MyClass is the name of your class.
As a note: If you override equals, it is strongly encouraged that you also override hashCode. If id is indeed an integer, then you might consider having hashCode just return id.

You need to check the type and "nullness" of the incoming object. You should also check whether or not this.id is null just to be thorough. You also are probably going to want to override Object.hashCode() as well so that Sets and Maps work like you want.
#Override
public boolean equals(Object obj) {
if ((obj == null) || (!getClass().isAssignableFrom(obj.getClass()))) {
return false;
}
if (this.id == null) {
return false;
} else {
return this.id.equals((ClassName)obj.getId());
}
}
#Override
public int hashCode() {
return this.id.hashCode();
}

Related

Lombok hashCode:: 1. Why good? 2. Why no compile error? [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed last year.
Improve this question
I have the following simple Java code,
import lombok.EqualsAndHashCode;
#EqualsAndHashCode
public class Test{
}
When I look at the delomboked code generated I see the following:
public class Test {
public Test() {
}
public boolean equals(Object o) {
if (o == this) {
return true;
} else if (!(o instanceof Test)) {
return false;
} else {
Test other = (Test)o;
return other.canEqual(this);
}
}
protected boolean canEqual(Object other) {
return other instanceof Test;
}
public int hashCode() {
int result = true;
return 1;
}
}
I don't understand the implementation of the hashCode(). How is this a good hashing method? And why is there no compile problem with int result = true;?
I suspect this is related to hashCode() being native, but I don't understand why I see this implementation.
UPDATE: My main question is in regards to the lack of compile error. If I add two fields for example I would have:
import lombok.EqualsAndHashCode;
#EqualsAndHashCode
public class Test{
private String name;
public int age;
}
and
...
public int hashCode() {
int PRIME = true;
int result = 1;
int result = result * 59 + this.age;
Object $name = this.name;
result = result * 59 + ($name == null ? 43 : $name.hashCode());
return result;
}
...
That you see the hashCode() method like this is probably an artifact of the tool you use to analyze the generated bytecode.
Internally the boolean values true and false are represented by the values 1 and 0 respectively. Some bytecode decompilers blindly translate 0 into false and 1 into true - this is what seems to be happening in your case.
The hashCode() method should read as
public int hashCode() {
int result = 1;
return 1;
}
Now to the question:
Is this a valid hashCode implementation?
Sure it is. The contracts for equals() and hashCode() state that for any two objects o1 and o2 when o1.equals(o2) is true then it must also be that o1.hashCode() == o2.hashCode().
Lomboks #EqualsAndHashCode annotation generates code so that two objects having the same field values are deemed equal (and therefore must have the same hashCode).
Since your class doesn't have any fields, all instances are considered equal and therefore must have the same hashCode. The actual value of the hashCode doesn't matter, as long as it is the same value for all instances.
Is the code that you see an error in the decompiler?
Yes, it clearly is (because the decompiler generates invalid source code).
Lombok itself contains an integrated "delombok" feature (https://projectlombok.org/features/delombok) and that feature creates for your first Test class the following source code (using Lombok 1.18.22):
public class Test {
#Override
public boolean equals(final Object o) {
if (o == this) return true;
if (!(o instanceof Test)) return false;
final Test other = (Test) o;
if (!other.canEqual((Object) this)) return false;
return true;
}
protected boolean canEqual(final Object other) {
return other instanceof Test;
}
#Override
public int hashCode() {
final int result = 1;
return result;
}
}
I think it's because your Test class doesn't have any field. So all instances of the class would be considered "equal" when using #EqualsAndHashCode. So the delomboked implementation reflects that.

Why do equals() implementations always start from self checking even when it's redundant? [duplicate]

This question already has answers here:
regarding using this in implementing equals for comparing objects in Java
(5 answers)
Closed 1 year ago.
I am learning to override Java's equals() method, and I can understand the correctness of many tutorials such as the following from https://www.baeldung.com/java-hashcode#handling-hash-collisions.
public class User {
private long id;
private String name;
private String email;
// standard getters/setters/constructors
#Override
public int hashCode() {
return 1;
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null) return false;
if (this.getClass() != o.getClass()) return false;
User user = (User) o;
return id == user.id
&& (name.equals(user.name)
&& email.equals(user.email));
}
// getters and setters here
}
My Question is that the implementation starts from self-checking, like
if (this == o) return true;
but this line seems to be redundant. If o references to the same object,
the last checking
User user = (User) o;
return id == user.id
&& (name.equals(user.name)
&& email.equals(user.email));
will be true as well.
I have googled a lot, but cannot find any topic related to it.
Why does every implementation of equals() start with self-checking even when there is no need to do that?
Is this a performance issue or something?
The first to call to == is an optimization. If this and o are the exact same object (i.e. this == o returns true), there's no need to perform the subsequent following operations of going over all the object's properties and comparing them one by one.

Easiest way to find the element is present in ENUM or not in JAVA? [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 3 years ago.
Improve this question
I need to find the specific string element is present in ENUM or not at runtime using java and based on that take action. What is the efficient way to do so.
A very minimal example given your requirements. Here is some documentation for Enums that you should look at as well. Enum info
Given the enum below:
enum TestEnum {
FOO,
BAR
}
You could simply call valueOf to determine if the String is a valid for that enum.
public boolean exampleTest(final String value) {
try {
TestEnum.valueOf(value);
return true;
} catch (final IllegalArgumentException | NullPointerException) {
// Log if desired
return false;
}
}
Note: Enum#valueOf is case sensitive so the String argument must match exactly.
exampleTest(“FOO”); // true
exampleTest(null); // false
exampleTest(“BAR”); // true
exampleTest(“bar”); // false
You can do like below -
public enum Direction {
NORTH("North"),
EAST("East"),
SOUTH("South"),
WEST("West")
private String dir;
Direction(String dir) {
this.dir = dir;
}
public String getDir() {
return dir;
}
}
to check with specific string you can do like below -
for(Direction dir : Direction.values())
{
//check your condition here
System.out.println(dir.name() + " :: "+ env.getDir());
}

Efficient way to build a key using two strings in java? [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about programming within the scope defined in the help center.
Closed 5 years ago.
Improve this question
Below is the code I have written to build a key using two strings. If either of them is null, empty or blank use the other string to build the key. However if both of them does not qualify, return an empty string. I would like to write a better and efficient piece of code. Here is my sample code
if (!StringAssistant.isBlank(string1) && !StringAssistant.isBlank(string2)) {
return StringAssistant.append(string1, string2);
}
if (StringAssistant.isBlank(string1) && !StringAssistant.isBlank(string2)) {
return string2;
}
if (!StringAssistant.isBlank(string1) && StringAssistant.isBlank(string2)) {
return string1;
}
return "";
You may do something as "simple" as :
return StringAssistant.append(StringAssistant.isBlank(string1)?"":string1,StringAssistant.isBlank(string2)?"":string2);
Simply append the two string and return the value
return string1+string2;
or if you want to use your StringAssistant.append
return return StringAssistant.append(string1, string2);
Notice that the empty string doesn't has an impact on the return value. So if you append the string and return it will result the same.
If the string can be null then you need to handle the null value separately. if either string is null then you can return an empty string. You can handle it in your append method.
You can refactor the code as shown below, I suggest you evaluate the isBlank for the both the strings first (so that for large strings you would get the results quicker):
boolean string1Blank = !StringAssistant.isBlank(string1);
boolean string2Blank = !StringAssistant.isBlank(string2);
if(string1Blank && string2Blank) {
return StringAssistant.append(string1, string2);
} else if(string1Blank) {
return string2;
} else if(string2Blank) {
return string1;
} else {
return "";
}

Why am I getting duplicate keys in Java HashMap? [duplicate]

This question already has answers here:
Java 1.7 Override of hashCode() not behaving as I would expect
(2 answers)
Closed 6 years ago.
I seem to be getting duplicate keys in the standard Java HashMap. By "duplicate", I mean the keys are equal by their equals() method. Here is the problematic code:
import java.util.Map;
import java.util.HashMap;
public class User {
private String userId;
public User(String userId) {
this.userId = userId;
}
public boolean equals(User other) {
return userId.equals(other.getUserId());
}
public int hashCode() {
return userId.hashCode();
}
public String toString() {
return userId;
}
public static void main(String[] args) {
User arvo1 = new User("Arvo-Part");
User arvo2 = new User("Arvo-Part");
Map<User,Integer> map = new HashMap<User,Integer>();
map.put(arvo1,1);
map.put(arvo2,2);
System.out.println("arvo1.equals(arvo2): " + arvo1.equals(arvo2));
System.out.println("map: " + map.toString());
System.out.println("arvo1 hash: " + arvo1.hashCode());
System.out.println("arvo2 hash: " + arvo2.hashCode());
System.out.println("map.get(arvo1): " + map.get(arvo1));
System.out.println("map.get(arvo2): " + map.get(arvo2));
System.out.println("map.get(arvo2): " + map.get(arvo2));
System.out.println("map.get(arvo1): " + map.get(arvo1));
}
}
And here is the resulting output:
arvo1.equals(arvo2): true
map: {Arvo-Part=1, Arvo-Part=2}
arvo1 hash: 164585782
arvo2 hash: 164585782
map.get(arvo1): 1
map.get(arvo2): 2
map.get(arvo2): 2
map.get(arvo1): 1
As you can see, the equals() method on the two User objects is returning true and their hash codes are the same, yet they each form a distinct key in map. Furthermore, map continues to distinguish between the two User keys in the last four get() calls.
This directly contradicts the documentation:
More formally, if this map contains a mapping from a key k to a value v such that (key==null ? k==null : key.equals(k)), then this method returns v; otherwise it returns null. (There can be at most one such mapping.)
Is this a bug? Am I missing something here? I'm running Java version 1.8.0_92, which I installed via Homebrew.
EDIT: This question has been marked as a duplicate of this other question, but I'll leave this question as is because it identifies a seeming inconsistency with equals(), whereas the other question assumes the error lies with hashCode(). Hopefully the presence of this question will make this issue more easily searchable.
The issue lies in your equals() method. The signature of Object.equals() is equals(OBJECT), but in your case it is equals(USER), so these are two completely different methods and the hashmap is calling the one with Object parameter. You can verify that by putting an #Override annotation over your equals - it will generate a compiler error.
The equals method should be:
#Override
public boolean equals(Object other) {
if(other instanceof User){
User user = (User) other;
return userId.equals(user.userId);
}
return false;
}
As a best practice you should always put #Override on the methods you override - it can save you a lot of trouble.
Your equals method does not override equals, and the types in the Map are erased at runtime, so the actual equals method called is equals(Object). Your equals should look more like this:
#Override
public boolean equals(Object other) {
if (!(other instanceof User))
return false;
User u = (User)other;
return userId.equals(u.userId);
}
OK, so first of all, the code doesn't compile. Missing this method:
other.getUserId()
But aside from that, you'll need to #Override equals method, IDE like Eclipse can also help generating equals and hashCode btw.
#Override
public boolean equals(Object obj)
{
if(this == obj)
return true;
if(obj == null)
return false;
if(getClass() != obj.getClass())
return false;
User other = (User) obj;
if(userId == null)
{
if(other.userId != null)
return false;
}
else if(!userId.equals(other.userId))
return false;
return true;
}
Like others answered you had a problem with the equals method signature. According to Java equals best practice you should implement equals like the following :
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
User user = (User) o;
return userId.equals(user.userId);
}
Same thing applies for the hashCode() method. see Overriding equals() and hashCode() method in Java
The Second Problem
you don't have duplicates anymore now, but you have a new problem, your HashMap contains only one element:
map: {Arvo-Part=2}
This is because both User objects are referencing the same String(JVM String Interning), and from the HashMap perspective your two objects are the same, since both objects are equivalent in hashcode and equals methods. so when you add your second object to the HashMap you override your first one.
to avoid this problem, make sure you use a unique ID for each User
A simple demonstration on your users :

Categories

Resources