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
Related
Q.1) As written in documentation of AbstractSet - "This class does not override any of the implementations from the AbstractCollection class." If it does not override or change add(Object o) or any other Collection interface contract implemented by AbstractCollection class, and merely inherits them and so as HashSet.
How do HashSet and other Set objects then enforce stipulations like no duplicate adding check or Hashtable way of inserting elements, which is totally different to how List or other Collection objects can add elements.
Q.2) In doc, for AbstractSet, it is written, AbstractSet merely adds implementation for equals and hashcode. However, in method details part, it is mentioned Object class has done overriding equals and hashcode method. Does AbstractSet only inherit without doing any change to these two methods? If so, what is the importance of AbstractSet class? Please clarify
Q1: How does HashSet enforce duplicate checks?
If you take a look at the implementation in java.util.HashSet, you'll see the following code:-
private static final Object PRESENT = new Object();
public boolean add(E e) {
return map.put(e, PRESENT)==null;
}
What happens is fairly simple; we use a private HashMap instance, which takes our provided value and inserts it as the key of the HashMap. The map's PRESENT value is never actually used or retrieved, but it allows us to use this backing map to verify whether or not the item exists in the Set.
If our provided value does not exist in the map, the call to map.put() will place the item in the map and return our object. Otherwise, the map remains unchanged and the method returns null. The HashMap is doing the hard work for the HashSet here.
This is different to the implementation provided by the AbstractCollection class, and hence the need to override.
Q2: AbstractSet's use of equals() & hashCode()
I think you have slightly misunderstood what AbstractSet is doing here. The purpose of AbstractSet is to provide a collection-safe implementation of equals and hashCode.
Equals checks are performed by verifying that we are comparing two Set objects, that they are of equal size, and that they contain the same items.
public boolean equals(Object o) {
if (o == this)
return true;
if (!(o instanceof Set))
return false;
Collection<?> c = (Collection<?>) o;
if (c.size() != size())
return false;
try {
return containsAll(c);
} catch (ClassCastException unused) {
return false;
} catch (NullPointerException unused) {
return false;
}
}
The hashCode is produced by looping over the Set instance, and hashing each item iteratively:
public int hashCode() {
int h = 0;
Iterator<E> i = iterator();
while (i.hasNext()) {
E obj = i.next();
if (obj != null)
h += obj.hashCode();
}
return h;
}
Any class extending from AbstractSet will use this implementation of equals() and hashCode() unless it overrides them explicitly. This implementation takes preference over the default equals and hashCode methods defined in java.lang.Object.
The documentation you provided are for Java 7, and I was checking the code of java 8 and I found the below so I think it isn't the same for java 7, still you can use the same methodology of checking the code when the documentation isn't very clear for you:
Q1: HashSet Overrides the add method in AbstractCollection you can easily check this if you open the HashSet code in some ide. If a parent doesn't override some methods doesn't mean its children can't do it.
Q2: Again by checking the code we notice that AbstractSet defines its own implementation of equals and hashCode methods. It also overrides the removeAll method of AbstractCollection.
I have a LinkedList of generic type State. In this LinkedList I have hundreds or even thousands of State objects. How can I, in the most efficient way to check if newly generated State object is already in the list?
State object:
public State(PlayerAddress player, LinkedList<BoxAddress> boxList, char[][] map, String solution, String stateHash) {
this.player = player;
this.boxList = boxList;
this.map = map;
this.solution = solution;
this.stateHash = stateHash;
boxListString = boxListToString(boxList);
mapString = mapString(map);
}
}
Additionally, State object consists of another generic objects as it is shown in the Constructor. How can I check if both State objects are the same in every aspect (PlayerAddress, LinkedList, etc.) ?
Have you tried the contains method? This could work. Also don't forget that you can overwrite stuff, so you could compare the hascodes as well by overwriting the hascode and compare methods.
In your case I would strongly suggest you will utilize the contains method. Which is the most efficient lookup for your case.
Looking at the java doc for contains:
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)).
So you should only need to overwrite equals for your State class. The hashcode, will be required for sets.
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.
I have to make an ArrayList that contains an object, the object has one int for year lets say 1
and I don't what another object with the same year 1.
If one object has the int = 1 , i dont want another object with that int(1) in my list.
i want to deny it.
Should I try using equal?
something like
#Override
public boolean equals(Object o){
Object object = (Object)o;
return this.getInt.equals(object.getInt());
}
Either use a Set...which explicitly disallows duplicates, or check if the list contains the element on insertion.
#Override
public boolean add(T element) {
if(contains(element)) {
return false;
} else {
return super.add(element);
}
}
Overriding equals wouldn't get you very far, as you'd be overriding it for the List itself (i.e. you'd be checking if two lists were equal).
Perhaps you can try using a HashMap linked that links that "int" with the object. That could be:
Map<Integer, Object> map = new HashMap<>();
map.put(object.getInt(), object);
...
//Each time you put a new object you could try this:
if(!map.contains(object.getInt()))
map.put(object.getInt, object);
//And you can retrieve your object by an int
int a = 1;
Object obj = map.get(1);
In this case, as the value is of type int, you can use equal operator.
public boolean equals(Object o){
Object object = (Object)o;
return (this.getInt()==object.getInt());
}
For this kind of requirement, ArrayList is not suggestible. As mentioned in the other answers try using HashMap.
Yes, you can. When you call
myArrayList.contains(myObejct);
the ArrayList will invode myObejct's equals method. So you can tell if the object is already in you list.
And I think you can change you method a little,
#Override
public boolean equals(Object o){
if (!(o instanceof YourClass))
return false;
YourClass object = (YourClass)o;
return this.getInt.equals(object.getInt());
}
because if you don't, the method "getInt" might cause a MethodNotFound exception.
Well, that is one way to approach the problem.
Your equals will probably work provided that you change Object object = (Object)o; to cast to the real class.
However, equals ought to cope with the case where o is not of the expected type. The contract requires you should return false rather than throwing a ClassCastException ...
You would then use list.contains(o) to test if an object with the same int value exists in the list. For example:
if (!list.contains(o)) {
list.add(o);
}
But when you override equals, it is best practice to also override hashcode ... so that your class continues to satisfy the equals / hashcode invariants. (If you neglect to do that, hash-based data structures will break for your class.)
However, this won't scale well, because the contains operation on an ArrayList has to test each element in the list, one at a time. As the list gets longer, the contains call takes longer ... in direct proportion; i.e. O(N) ... using Big O complexity notation.
So it may be better to use a Set implementation of some kind instead on ArrayList. Fepending on which set implementation you choose, you will get complexity of O(1) or O(logN). But the catch is that you will either have to to implement hashcode (for a HashSet or LinkedHashSet), or implement either Comparable or a Comparator (for a TreeSet).
hi i've seen this post how to implement the union and intersection when it you have two sets of data,that are strings.how can i do the same when my sets contain objects,and i want to get the union of only one property of each object?
But I want to override them somehow so that it wont add an object if there's an object already in my set that has the same value in a selected property.If i'm not clear enough tell me so i can write an example.
I think the best way to do this is to use a ConcurrentMap.
ConcurrentMap<String, MyType> map = new ConcurrentHashMap<>();
// the collection to retain.
for(MyType mt: retainedSet) map.put(mt.getKey(), mt);
// the collection to keep if not duplicated
for(MyType mt: onlyIfNewSet) map.putIfAbsent(mt.getKey(), mt);
// to get the intersection.
Set<String> toKeep = new HashSet<>();
for(MyType mt: onlyIfNewSet) toKeep.add(mt.getKey());
// keep only the keys which match.
map.keySet().retainAll(toKeep);
Google Guava, has Sets class which contains these methods and many more.
As in this answer, use Collection methods retainAll(Collection)- intersection and #addAll(Collection)- union.
Since those methods use equals, you also have to override equals method in your Class and implement one-property based comparison.
In case it's simple comparison, here's an example (generated by my IDEA):
public class Main {
private Integer age;
...
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Main main = (Main) o;
if (age != null ? !age.equals(main.age) : main.age != null) return false;
return true;
}
Intersection is using contains, which uses equals. You should implement equals() method on the class that you want to do intersection.
I didn't find specific comments about set.addAll() implementation, but most probably it also uses equals() to determine if an object is already on the set.
If you want to compare only by a field, your equals() should only compare this field.