contains method in java - java

i know this is simple but im going crazy
public class CadastroPessoas {
Collection<Pessoa> lista;
Pessoa p;
public static void main(String[] args) {
CadastroPessoas p = new CadastroPessoas();
}
public CadastroPessoas() {
lista = new ArrayList<>();
for (int i = 0; i < 10; i++) {
p = new PessoaFisica();
p.setNome(String.format("name %02d", i));
p.setEmail(String.format("mail%02d#mail.com", i));
p.setTelefone(String.format("122312%02d", i));
if (!lista.contains(p)) {
lista.add(p);
}
}
for (Pessoa pessoa : lista) {
System.out.println(pessoa.toString());
}
} }
i want add various "PessoaFisica" to my collection but i need to check if this person exists, and with this code i just add the 1st one, what is wrong in my code

From the documentation (http://docs.oracle.com/javase/7/docs/api/java/util/Collection.html) about the contains method of the Collection interface:
Returns true if this collection contains the specified element. More
formally, returns true if and only if this collection contains at
least one element e such that (o==null ? e==null : o.equals(e)).
o.equals(e)
Calls the non-overridden method of the class Object
I suggest you to override the method equals, for example
public class Pessoa
{
#Override
public boolean equals(Pessoa pessoa)
{
//You check if the fields are equal, if not, return false
if(this.field != pessoa.field) return false;
else if(this.field2 != pessoa.field2) return false;
return true;
}
}

Two inputs from my side here.
1)You are probably using the wrong collection interface for your purpose here. If you need to prevent duplicates you might be better off using a Set eg. HashSet or TreeSet.
2)As you have been told, you will need to override equals method in PessoaFisica and implement your own identity check, while you are at it do not forget to override hashCode() method. There is a contract between equals and hashCode. Two equal objects must have equal hashCodes.Most IDEs will generate this code for you, in idea go to Code->Generate->HashCode And Equals. It will ask you the fields to include and auto generate the two methods.

from javadoc for the list interface :
boolean contains(Object o)
Returns true if this list contains the specified element. More formally, returns true if and only if this list contains at least one element e such that (o==null ? e==null : o.equals(e))
So, it looks like that you are not overriding the equals method in PessoaFisica class.

Related

Overide equals method in class with aggregation Arraylist

I need to override equals() and hashCode() methods in Java class. But this class contains a list of objects. How should I implement the part of the code with comparing ArrayList field?
The code looks like:
public class FirstClass {
private List<SecondClass> list = new ArrayList<>();
equals() {
//how i should implement equals for list field?
}
hashCode() {
}
}
I can only add that SecondClass has well-working equals and hashCode methods.
I know about symmetric, transition and others important things, but I only want to focus on this problem with ArrayList field.
ArrayList (and any List implementation) is required to override equals and hashCode properly, as stated in the List javadoc:
boolean java.util.List.equals(Object o)
Compares the specified object with this list for equality. Returns true if and only if the specified object is also a list, both lists 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)).) In other words, two lists are defined to be equal if they contain the same elements in the same order. This definition ensures that the equals method works properly across different implementations of the List interface.
int java.util.List.hashCode()
Returns the hash code value for this list. The hash code of a list is defined to be the result of the following calculation:
int hashCode = 1;
for (E e : list) {hashCode = 31*hashCode + (e==null ? 0 : e.hashCode());}
Therefore all you need is to call list.equals() and list.hashCode().
public class FirstClass
{
private List<SecondClass> list = new ArrayList<>();
#Override
public boolean equals(Object other) {
if (this == other)
return true;
if (!(other instanceof FirstClass))
return false;
FirstClass fc = (FirstClass) other;
return list.equals(fc.list);
}
#Override
public int hashCode() {
return list.hashCode ();
}
}
This is assuming list can never be null. Otherwise, some additional checks must be added.

Debug equals() and hashCode() in Eclipse

I have below code and I have placed break points on overridden equals() and hashCode() methods of ContainerBean. When I run below application in debug mode, debugger stops at hashCode() only for System.out.println line and not while trying to remove element from List.
import java.util.ArrayList;
import java.util.List;
public class ListRemovalDriver {
public static void main(String[] args) {
List<ContainerBean> remitClaims = new ArrayList<>();
ContainedBean addedRemit1 = new ContainedBean();
addedRemit1.setRemitId(12345L);
ContainerBean added1 = new ContainerBean();
added1.setRemitBean(addedRemit1);
remitClaims.add(added1);
ContainedBean removedRemit1 = new ContainedBean ();
removedRemit1.setRemitId(12345L);
ContainerBean removed1 = new ContainerBean ();
removed1.setRemitBean(removedRemit1);
System.out.println("List before valid removal" + remitClaims);
remitClaims.remove(removed1);
System.out.println("List after valid removal" + remitClaims);
}
}
Am I missing something?
Would overridden equals() in ContainerBean not be called while removing element from list?
EDIT
I forgot to mention that hashCode() and equals() are working as expected i.e. elements getting removed as per equals() logic but its only debugger that is not taking me there on list remove function call.
Since you did not give the code I have to guess: You did not override equals, but instead added an overload like this:
public boolean equals(ContainerBean c) { ... }
This will not work because equals(Object) is called.
Change your equals implementation to take an argument of type Object and it will both get called and stopped at in eclipse debugger.
Would overridden equals() in ContainerBean not be called while
removing element from list ?
Yes, when you are using remove(Object o), then equals() in ContainerBean will be called to check the equality of the object and then remove it from the list as mentioned in the ArrayListAPI below (emphasis mine):
Removes the first occurrence of the specified element from this list,
if it is present. If the list does not contain the element, it is
unchanged. More formally, removes the element with the lowest index i
such that (o==null ? get(i)==null : o.equals(get(i))) (if such an
element exists). Returns true if this list contained the specified
element (or equivalently, if this list changed as a result of the
call).
But, on the other side, when you are removing an element using the index of the list (i.e., using remove(int index)), then there will NOT be any equals() check.
You can look here
Source code of ArrayList from jdk 7,
ArrayList.remove(Object o)
it invokes equals method to verify the object to remove from the collection
for (int index = 0; index < size; index++)
if (o.equals(elementData[index])) {
fastRemove(index);
return true;
}
}
source: ArrayList Source

Checking if ArrayList<> cointains a object dont work

My app downloading a Events from sqldatabase and add it to ArrayList<>. It do aduplicate so I wrote:
public static ArrayList<Events> list = new ArrayList<Events>();
static void addevhlp(Events e){
if (list.contains(e)){
Log.d("","it cointains")
}
else {
list.add(e);
}
}
But it never say me the list cointans element. What I'm doing wrong?
you have to override equals in Events, and define when two events are equals. The default implementation checks for equal object's reference. For instance, if your Events class has an int id field
#Override
public boolean equals(Object o) {
if (!(o instanceof Events)) {
return false;
}
Events event = (Events) o;
return id == event.id;
}
You should overrides equals and hashCode in your Events object.
See :
Best implementation for hashCode method for detail about hashCode
According to the documentation about ArrayList.contains:
Returns true if this list contains the specified element. More
formally, returns true if and only if this list contains at least one
element e such that (o==null ? e==null : o.equals(e)).
So, contains uses the equals implementation of your Events class to check if it holds the object.
if (list.contains(e))
If the events e has the same Reference than the one you have in the ArrayList the contains will work.
but If you want to check if the value is the same, but with a different Reference, you have to check if the properties of your events are exists or equals.
or you can simply use LINQ with List instead of ArrayList
C# how to determine, whether ArrayList contains object with certain attribute

custom equals() method does not work properly

I've implemented the Apriori algorithm. it works pretty well, but I ran into a strange problem: I've defined a Rule class to maintain the generated rules.
Here it is:
public class Rule
{
private Set<Integer> left;
private Set<Integer> right;
private LookupArtist lookupArtist;
public Rule(LookupArtist lookupArtist){
left = new HashSet<>();
right = new HashSet<>();
this.lookupArtist = lookupArtist;
}
#Override
public boolean equals(Object another){
Rule rule = (Rule) another;
if(this.left.equals(rule.getLeft()) && this.right.equals(rule.getRight()))
return true;
else
return false;
}
#Override
public String toString(){
/* print the object */
}
public void addToLeft(Integer toAdd){
left.add(toAdd);
}
public void addToRight(Integer toAdd){
right.add(toAdd);
}
public Set<Integer> getLeft(){
return left;
}
public Set<Integer> getRight(){
return right;
}
}
I also implemented the equals() method in a different way just to try:
#Override
public boolean equals(Object another){
Rule rule = (Rule) another;
boolean flag = true;
for(Integer artist : left){
if(flag)
if(!rule.left.contains(artist))
flag=false;
}
if(flag)
for(Integer artist : right){
if(flag)
if(!rule.right.contains(artist))
flag=false;
}
return flag;
}
The LookupArtist object is used to map the integers to some Strings.
The problem is that when I print out the rules I found that some rules appear two times. I also found in debug mode some replicated rules, so it isn't be a print problem. The rules are saved in a map like this:
static Map<Rule, Float> rules;
.
.
.
Rule rule = new Rule(lookupArtist);
for(int j=0;j<i;j++){
rule.addToLeft(a[j]);
}
for(int j=i;j<a.length;j++){
rule.addToRight(a[j]);
}
if(!rules.containsKey(rule)){
rules.put(rule, getRuleConfidence(rule));
}
Any idea where the problem can be?
When using a HashSet for storing objects of a class that has a custom equals implementation, you must have a matching custom implementation for hashCode.
If two objects are equal (according to the custom equals implementation), they must have the samehashCode. In the code you posted, I don't see an overriding ofhashCodein theRule` class.
When you add an instance to the HashSet, hashCode method is used to determine the index in the hash table in which the instance will be stored. Then, the linked list of instances stored in this index is iterated to see if the instance is already there. When iterating over that list, equals is used. If two objects that are equal are mapped by hashCode to different indices in the HashSet, the duplication won't be detected, since they would be stored in separate linked lists.
This is stated in the Javadoc of equals :
* Note that it is generally necessary to override the <tt>hashCode</tt>
* method whenever this method is overridden, so as to maintain the
* general contract for the <tt>hashCode</tt> method, which states
* that equal objects must have equal hash codes.
And in the Javadoc of hashCode :
* <li>If two objects are equal according to the <tt>equals(Object)</tt>
* method, then calling the <code>hashCode</code> method on each of
* the two objects must produce the same integer result.
You should always override hashCode when you override equals and vice versa.
Add something like this to your Rule class:
#Override
public int hashCode() {
return left.hashCode()
^ right.hashCode()
^ lookupArtist.hashCode();
}
Here is a good answer explaining why it's important to override both.
Also, your equals method can be written as
#Override
public boolean equals(Object another){
Rule rule = (Rule) another;
return left.equals(rule.left)
&& right.equals(rule.right)
&& lookupArtist.equals(rule.lookupArtist);
}
A final remark: Your other attempt at the equals-implementation is not symmetrical, i.e. it's not the case that rule1.equals(rule2) if and only if rule2.equals(rule1). That's a violation of the contract of equals.
And where is your hashCode() method? It is also very important :)

Java ArrayList Contain always return false although it contain the same value

This is my Hole Class
class Hole {
public int a;
public int b;
Hole(int a, int b) {
this.a = a;
this.b = b;
}
So i adding an ArrayList that contain several several hole
public void checkPathLoop(int x, int y) {
//rough code
ArrayList<Hole> leftFlowInnerHole = new ArrayList<>();
//left holes rules
leftFlowInnerHole.add(new Hole(0, 1));
leftFlowInnerHole.add(new Hole(1, 5));
leftFlowInnerHole.add(new Hole(5, 4));
leftFlowInnerHole.add(new Hole(0, 4));
when i add
Hole userInputHole = new Hole(0,1);
System.out.print(leftFlowInnerHole.contain(userInputHole));
it always return false !! it suppose to return true.
Is there anything i miss ??
Thank you in advance
You need to override the equals method herited from the Object class (and hence also hashCode to respect the contract, see Why do I need to override the equals and hashCode methods in Java? ) in your Hole class.
Returns true if this list contains the specified element. More
formally, returns true if and only if this list contains at least one
element e such that (o==null ? e==null : o.equals(e)).
Basically the default equals implementation is an == comparison between the two objects
public boolean equals(Object obj) {
return (this == obj);
}
Since you created two different objects, while they have the same value as attributes they're two distincts objects and hence this == obj returns false.
If you did :
Hole a = new Hole(0,1);
leftFlowInnerHole.add(a);
System.out.print(leftFlowInnerHole.contains(a));
You'll see that it outputs true.
You should overide the equals method of the Hole class:
#Override
public boolean equals(Object obj) {
if (obj == this) {
return true;
}
if (!(obj instanceof Hole)) {
return false;
}
Hole other = (Hole) obj;
return a == other.a && b == other.b;
}
contains() method checks the equal() method on Object while checking .
You have to ovveride equals method in order to make it work.
public boolean contains(Object o)
Returns true if this list contains the specified element. More formally, returns true if and only if this list contains at least one element e such that (o==null ? e==null : o.equals(e)).
Edit:
If you not ovveriding equals method, Then default Object equals method executes and, as per docs of Equals method
The equals method for class Object implements the most discriminating possible equivalence relation on objects; that is, for any non-null reference values x and y, this method returns true if and only if x and y refer to the same object (x == y has the value true).
So your userInputHole == leftFlowInnerHole is always false as they are pointing to different instances.
Hence to avoid the default implementation ,you just ovveride that equals in yout class and provide your implementation.
An efficient equals(Object o) implementation
This is not working
if(priceidslist.contains(extraId)){
//Not working
}
I just added this lines for checking that condition in (for -loop ),then its working fine
String gh = String.valueOf(priceidslist.get(j));
if(gh.equals(extraId)){
rw.put("extraPrice",pricelist.get(j));
}

Categories