I have a Class Levels which has a hashMap declared.
public class Levels{
private final Map<Unit, Object1> rateUnitCost;
public Levels(Map<Unit, Object1> levels) {
this.rateUnitCost = new HashMap<Unit, Object1>(levels);
}
public Object1 getCoverageLevel(Unit unit, Phase aP) {
return rateUnitCost.get(unit);
}
}
I am calling getCoverageLevel() method from other class and i am instantiating the Levels class rateUnitCost property as well from another class.
When seeing in debugger i am finding this value for rateUnitCost and unit object.
rateUnitCost: - Hash Map Values
rateUnitCost HashMap<K,V> (id=1248)
[0] HashMap$Node<K,V> (id=1266)
key >Unit (id=1249)
amount Money (id=1267)
flags ArrayList<E> (id=1268)
procedureId 7156
ParticipationId 104152413
value >Object1 (id=1250)
Now value of unit object is below :-
unit Unit (id=1251)
amount Money (id=1258)
flags ArrayList<E> (id=1259)
procedureId 7156
ParticipationId 104152413
when i match the value of key with this object then its matching .
But at the time of rateUnitCost.get(unit) its returning null even though Object1 is set. Object1 is getting returned from other class using below line: -
return new Object1();
Can anyone please help me to resolve this mystery.?
BasicUnit is a class which is implementing the Unit interface. BasicUnit have equals method as below :-
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
BasicUnit basicUnit = (BasicUnit) o;
if (flags != basicUnit.flags) return false;
if (procedureId != basicUnit.procedureId) return false;
if (ParticipationId != basicUnit.ParticipationId) return false;
if (amount != null ? !amount.equals(basicUnit.amount) : basicUnit.amount != null) return false;
return true;
}
and HashCode :-
public int hashCode() {
int result = procedureId;
result = 31 * result + ParticipationId;
result = 31 * result + (amount != null ? amount.hashCode() : 0);
result = 31 * result + (flags == null ? null : flags.hashCode());
return result;
}
if (flags != basicUnit.flags) return false;
You are checking for whether your Unit objects have exactly the same ArrayList of flags. This is not an equals()-type equality check; this is checking for literally the same ArrayList of flags. Now, you haven't provided the constructor etc, but I highly doubt you are reusing the same ArrayList.
Check for !(flags.equals(basicUnit.flags)) instead. Do note that ArrayList.equals() uses the E.equals() implementation, so be sure that that is implemented.
Also, note that ArrayList.equals() checks for the same list entries in the same order. I don't know if the order of your flags matters but I suspect it probably does not. You might consider making your flag collection a Set if this is the case.
Related
I know that the below code gives the index of that particular element in java.
List<String> list = new ArrayList<>();
list .add("100");
Log.d("TAG",String.valueOf(list.indexOf("300")));
But how to get the index of an element while using a helper Class?
List<HelperClass> Arraylist= new ArrayList<>();
Arraylist.add(new HelperClass(name, email, phoneno));
Log.d("TAG", String.valueOf(new HelperClass(Arraylist.indexOf(name,email,phoneno))));
I searched everywhere for this but couldn't find. Can someone tell me how to find index of a particular item in arraylist while using modal to add data?
Obviously what I have tried is wrong and it shows red line under the whole line but I just typed that code for your understanding of what I want to achieve. Can someone give me a way please?
Helper
#Override
public int hashCode() {
int result = getName() != null ? getName().hashCode() : 0;
result = 31 * result + (Email != null ? Emaail.hashCode() : 0);
result = 31 * result + (PhoneNo!= null ? PhoneNo.hashCode() : 0);
return result;
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Helper)) return false;
Helperthat = (Helper) o;
if (getName() != null ? !getName().equals(that.getName()) : that.getName() != null)
return false;
if (Email != null ? !Email.equals(that.Email) : that.Email != null)
return false;
if (PhoneNo != null ? !PhoneNo.equals(that.PhoneNo) : that.PhoneNo != null)
return false;
}
ArrayList#indexOf uses the Object#equals comparison method.
If you want to be able to lookup a HelperClass instance inside a Collection, you need to provide your own, overridden, equals method, and possibly also the hashCode one, for use with other, specific, Collection implementations (Map, Set, etc.).
class HelperClass {
...
#Override
public boolean equals(final Object object) {
if (object == this) {
return true;
}
if (!(object instance of HelperClass)) {
return false;
}
final HelperClass other = (HelperClass) object;
return name.equals(other.name) &&
email.equals(other.email) &&
phone.equals(other.phone);
}
}
You obviously need to have an appropriate HelperClass instance to find a match.
final String name = "Name";
final String email = "Email";
final String phone = "Phone";
final HelperClass first = new HelperClass(name, email, phone);
final HelperClass second = new HelperClass(name, email, phone);
final List<HelperClass> helpers = new ArrayList<>(8);
helpers.add(first);
final int index = helpers.indexOf(second); // index = 0
indexOf requires the object as input. If it does not find the object you are passing in, it will return -1. You need to pass the object whose location in the arraylist you are looking for as the input into the indexOf function.
Solution :
create a HelperClass to pass into the indexOf method:
.indexOf(new HelperClass(name, email, phoneno));
However that change by itself will still return -1. See the api doc for indexOf:
public int indexOf(Object o)
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.
It's using equals to decide whether it's found a match. You should have overridden the equals method on your HelperClass class, so it's using the default implementation in java.lang.Object, which compares the references, and only returns true if the two references HelperClass to the same object.
Override equals and hashcode on your HelperClass class, like:
#Override public boolean equals(Object other) {
if (!(other instanceof HelperClass)) {
return false;
}
HelperClass otherHelperClass = (HelperClass)other;
return otherHelperClass.x == this.x && otherHelperClass.y == this.y;
}
#Override public int hashCode() {
return x + y; // same values should hash to the same number
}
i'm new in java collections so i tried to codes using Map.
i set my collection like this
Map<Integer, Person> people = new HashMap<>();
people.put(1, new Person("Arnold", "Maluya", 25));
people.put(2, new Person("Mison", "Drey", 3));
people.put(3, new Person("James", "Valura", 54));
people.put(4, new Person("Mikee", "Sandre", 24));
so my goal is i want to check if people contains object like "new Person("Arnold", "Maluya", 25)" so what i did is this
boolean test = people.containsValue(new Person("Arnold", "Maluya", 25));
System.out.println(test);
which is i getting "false" result. so am i getting it right so if sumthing is wrong what did i miss?
Implement an equals, example:
public class Person {
private String name;
private String lastName;
private String age;
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Person person = (Person) o;
if (name != null ? !name.equals(person.name) : person.name != null) return false;
if (lastName != null ? !lastName.equals(person.lastName) : person.lastName != null) return false;
return age != null ? age.equals(person.age) : person.age == null;
}
#Override
public int hashCode() {
int result = name != null ? name.hashCode() : 0;
result = 31 * result + (lastName != null ? lastName.hashCode() : 0);
result = 31 * result + (age != null ? age.hashCode() : 0);
return result;
}
}
The methods hashCode() and equals() play a distinct role in the objects you insert into Java collections.
equals() is used in most collections to determine if a collection contains a given element.
When inserting an object into a hastable you use a key. The hash code of this key is calculated, and used to determine where to store the object internally. When you need to lookup an object in a hashtable you also use a key. The hash code of this key is calculated and used to determine where to search for the object.
When you use your custom java objects in collections, its always advisable to override hashCode() & equals() methods, to avoid weird behaviors.
The behavior is correct as you are not overriding the equals method in Person class. Map will consult with equals method of the object stored in it to identify whether the query is matching with stored values. You must override the equals method in your object and implement logic appropriately to determine whether object passed as an argument is matching or not.
Note: Below code doesn't check for null values and hence may throw an exception. You need to put additional conditions to avoid null pointer exceptions.
#Override
public boolean equals(Object obj) {
if (!(obj instanceof Person)) {
return false;
}
Person other = (Person) obj;
if ((other.firstName.equals(this.firstName)) && (other.lastName.equals(this.lastName))
&& (other.age == this.age)) {
return true;
}
return false;
}
i have a problem with the contains() method of TreeSet. As I understand it, contains() should call equals() of the contained Objects as the javadoc says:
boolean java.util.TreeSet.contains(Object o): Returns true if this set
contains the specified element. More formally, returns true if and
only if this set contains an element e such that (o==null ? e==null :
o.equals(e)).
What I try to do:
I have a list of TreeSets with Result Objects that have a member String baseword. Now I want to compare each TreeSet with all Others, and make for each pair a list of basewords they share. For this, I iterate over the list once for a treeSet1 and a second time for a treeSet2, then I iterate over all ResultObjects in treeSet2 and run treeSet1.contains(ResultObject) for each, to see if treeSet1 contains a Result Object with this wordbase. I adjusted the compareTo and equals methods of the ResultObject. But it seems that my equals is never called.
Can anyone explain me why this doesn't work?
Greetings,
Daniel
public static void getIntersection(ArrayList<TreeSet<Result>> list, int value){
for (TreeSet<Result> treeSet : list){
//for each treeSet, we iterate again through the list of TreeSet, starting at the TreeSet that is next
//to the one we got in the outer loop
for (TreeSet<Result> treeSet2 : list.subList((list.indexOf(treeSet))+1, list.size())){
//so at this point, we got 2 different TreeSets
HashSet<String> intersection = new HashSet<String>();
for (Result result : treeSet){
//we iterate over each result in the first treeSet and see if the wordbase exists also in the second one
//!!!
if (treeSet2.contains(result)){
intersection.add(result.wordbase);
}
}
if (!intersection.isEmpty()){
intersections.add(intersection);
}
}
}
public class Result implements Comparable<Result>{
public Result(String wordbase, double result[]){
this.result = result;
this.wordbase = wordbase;
}
public String wordbase;
public double[] result;
public int compareTo(DifferenceAnalysisResult o) {
if (o == null) return 0;
return this.wordbase.compareTo(o.wordbase);
}
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result
+ ((wordbase == null) ? 0 : wordbase.hashCode());
return result;
}
//never called
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
DifferenceAnalysisResult other = (DifferenceAnalysisResult) obj;
if (wordbase == null) {
if (other.wordbase != null)
return false;
} else if (!wordbase.equals(other.wordbase))
return false;
return true;
}
}
As I understand it, contains() should call equals() of the contained Objects
Not for TreeSet, no. It calls compare:
A NavigableSet implementation based on a TreeMap. The elements are ordered using their natural ordering, or by a Comparator provided at set creation time, depending on which constructor is used.
...
Note that the ordering maintained by a set (whether or not an explicit comparator is provided) must be consistent with equals if it is to correctly implement the Set interface.
Your compareTo method isn't currently consistent with equals - x.compareTo(null) returns 0, whereas x.equals(null) returns false. Maybe you're okay with that, but you shouldn't expect equals to be called.
I have a class for a string-number pair. This class has the method compareTo implemented.
A method of another class returns a collection of elements of the pair type.
I wanted to perform a unit test on this method, and therefore wrote the following:
#Test
public void testWeight() {
Collection<StringNumber<BigDecimal>> expected = new Vector<StringNumber<BigDecimal>>();
expected.add(new StringNumber<BigDecimal>("a", BigDecimal.ONE));
expected.add(new StringNumber<BigDecimal>("b", BigDecimal.ONE));
Collection<StringNumber<BigDecimal>> actual = new Vector<StringNumber<BigDecimal>>();
expected.add(new StringNumber<BigDecimal>("a", BigDecimal.ONE));
expected.add(new StringNumber<BigDecimal>("b", BigDecimal.ONE));
//Collection<StringNumber<BigDecimal>> actual = A.f();
assertEquals(expected, actual);
}
But as you can see, the assertion fails, even though the elements in the collections are identical. What can be the reason?
The error I get is
java.lang.AssertionError: expected: java.util.Vector<[a:1, b:1]>
but was: java.util.Vector<[a:1, b:1]>
Which does not make scene to me.
Your StringNumber class requires equals() method. Then it will work. Assuming this class contains string and number fields (auto-generated by my IDE):
#Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (!(o instanceof StringNumber)) {
return false;
}
StringNumber that = (StringNumber) o;
if (number != null ? !number.equals(that.number) : that.number != null) {
return false;
}
return !(string != null ? !string.equals(that.string) : that.string != null);
}
#Override
public int hashCode() {
int result = string != null ? string.hashCode() : 0;
result = 31 * result + (number != null ? number.hashCode() : 0);
return result;
}
Few remarks:
Two Vector's (why are you using such archaic data structure) are equal if:
both [...] have the same size, and all corresponding pairs of elements in the two lists are equal. (Two elements e1 and e2 are equal if (e1==null ? e2==null : e1.equals(e2)).)
That's why overriding equals() is required.
when implementing equals() you must implement hashCode(). Not required here, but better be safe than sorry: What issues should be considered when overriding equals and hashCode in Java?.
I need to implement equals() and hashCode() for an Address class.
I believe,the non null fields are taken to determine hashCode() and equals().In my application,Any of the fields except addressLine1 and country can be null.If that is the case,what happens if two different addresses have the same addressline1 and country?
Address1:(in state of NH which is omitted by user)
addressline1:111,maple avenue
country: US
Address2:
addressline1:111,maple avenue
state: Illinois
country: US
In such cases if I build a hashCode based only on non null fields ,it will give same for both addresses above.
Is this the right way to create hashCode?
int hash = addressline.hashCode();
if(addressLine2!=null){
hash += addressLine2.hashCode();
}
and so on...
Typically you would check whether one is null and the other is not in your equals method. For hashcode, you would just use 0 as the null hashcode. Example:
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((addressLine1 == null) ? 0 : addressLine1.hashCode());
result = prime * result + ((state == null) ? 0 : state.hashCode());
result = prime * result + ((country == null) ? 0 : country.hashCode());
return result;
}
If you use an IDE, it will usually generate these for you. In eclipse, choose Source, Generate equals and hashcode and it will let you select the fields you want to be a part of your equals and hashcode methods. For the equals method and your fields, this is what eclipse creates:
public boolean equals(Object obj) {
if (this == obj) return true;
if (obj == null) return false;
if (getClass() != obj.getClass()) return false;
YourClass other = (YourClass) obj;
if (addressLine1 == null) {
if (other.addressLine1 != null) return false;
} else if (!addressLine1.equals(other.addressLine1)) return false;
if (country == null) {
if (other.country != null) return false;
} else if (!country.equals(other.country)) return false;
if (state == null) {
if (other.state != null) return false;
} else if (!state.equals(other.state)) return false;
return true;
}
I would use that as a starting point and make any changes you think are neccessary from there.
Even fields that are null should be compared for equality. Use code like the following
to compare two fields of nonprimitive types, like String:
this.addressline==null ? other.addressline==null : this.addressline.equals(other.addressline)
For hash codes, use the same fields you used in equals, but you can treat null values as
having a hash code of 0 (or any other hash code value).
Here's the canonical question:
What issues should be considered when overriding equals and hashCode in Java?
And here are discussions of libraries that help you implement these methods properly:
Apache Commons equals/hashCode builder (also discusses Guava)