The problem with your code is not the removeDuplicates method. Instead is probably the equals method in the Road class. List.contains(...) uses this equals method to compare if the list contains the given element. So to make your code work as expected you should override the equals method in the Road class to perform the needed comparison.
Depending on the Road class implementation this could look like this for example:
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Road road = (Road) o;
return Objects.equals(road.x, x) &&
Objects.equals(road.y, y) &&
Objects.equals(imgPath, road.imgPath) &&
Objects.equals(color, road.color);
}
@Override
public int hashCode() {
return Objects.hash(x, y, imgPath, color);
}
As already pointed out in the comments these methods are usually generated using your IDE and only adjusted when needed. When adjusting them you have to take into consideration that there is a contract (which can be found in the docs) between equals and hashcode which has to be considered for various reasons (for example using hashsets).
Answer from Jakob Em on Stack OverflowThe problem with your code is not the removeDuplicates method. Instead is probably the equals method in the Road class. List.contains(...) uses this equals method to compare if the list contains the given element. So to make your code work as expected you should override the equals method in the Road class to perform the needed comparison.
Depending on the Road class implementation this could look like this for example:
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Road road = (Road) o;
return Objects.equals(road.x, x) &&
Objects.equals(road.y, y) &&
Objects.equals(imgPath, road.imgPath) &&
Objects.equals(color, road.color);
}
@Override
public int hashCode() {
return Objects.hash(x, y, imgPath, color);
}
As already pointed out in the comments these methods are usually generated using your IDE and only adjusted when needed. When adjusting them you have to take into consideration that there is a contract (which can be found in the docs) between equals and hashcode which has to be considered for various reasons (for example using hashsets).
Make sure you have overridden equals and hashCode methods in the class, Road something like:
@Override
public boolean equals(Object obj) {
Road other = (Road) obj;
return Objects.equals(imgPath, other.imgPath) && Objects.equals(color, other.color)
&& Objects.equals(x, other.x) && Objects.equals(y, other.y);
}
@Override
public int hashCode() {
return Objects.hash(imgPath, color, x, y);
}
Also, instead of writing so many lines in your method, you can write just one line using Stream API as follows:
private List<Road> removeDuplicates(List<Road> array) {
return array.stream().distinct().collect(Collectors.toList());
}
if it's just for backwards compatibility, why not deprecate contains(Object) and create a contains(E)?
Because contains(Object) and contains(E) have the same type erasure (as you can see in this code sample) and hence would cause compilation errors. Also, deprecating methods was not an option, the top priority back then was to make legacy code work.
Because there is no need to have a template here : this would only prevent some tests and if an object isn't of the required class the method would answer false in any case.
It's much simpler to have in your code a simple test checking if the return of the function is a boolean than a test and a try/catch. The few cases where having a type checked at compile time would allow to find a bug aren't worth the overhead.
What is the difference between a HashSet and an ArrayList in Java?
How do you create a HashSet in Java?
How do you remove duplicates from a list in Java?
java --version
openjdk 17.0.11 2024-04-16
OpenJDK Runtime Environment (build 17.0.11+9-Debian-1deb12u1)
OpenJDK 64-Bit Server VM (build 17.0.11+9-Debian-1deb12u1, mixed mode, sharing)
Hello!
According to OpenJDK ArrayList.contains() returns true if the element is found, however, the following code proves otherwise when passing the the string "123abc и"
-snip
// Holds all the letters, numbers and symbols from grapheme
var localList = new ArrayList<JmeString>();
localList.addAll(grapheme.getValues());
this.pout(localList); // prints out all the elements in the list
for(int i = 0; i != phrase.length(); i++){
if(!localList.contains(phrase.at(i).toString()) ||
!localList.contains(phrase.at(i).toUpperCase() ){
super.pout(phrase.at(i) + " is in the array");
}else{
super.pout(phrase.at(i) + " is not in the array");
}
}output
[a, e, i, o, u, à, â, ä, æ, è, ê, ë, î, ï, ô, œ, ù, û, ü, á, é, í, ó, ú, b, c, d, f, g, h, j, k, l, m, n, p, q, r, s, t, v, w, x, y, z, ç, ñ, ~, !, @, #, $, %, ^, &, *, (, ), -, _, =, /, +, {, }, [, ], |, ?, ¿, ., , 0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
1 is not in the array // is an element of the list
2 is not in the array // is an element of the list
3 is not in the array // is an element of the list
a is not in the array // is an element of the list
b is not in the array // is an element of the list
c is not in the array // is an element of the list
is not in the array //Blank is an element of the list
и is not in the array // This element does not exist in the List
Now the question is:
What am I doing wrong?
Have I misunderstood the algorithm?
or is the OpenJDK 17 page wrong?
Thanks in advance.
It checks for each element, if it is equal() to the element you are testing against.. Meaning, if the two elements pass the equals() method test, the contains() method will return true for them, if the equals() method returns false, so will the contains() method.
From the Java doc:
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)).
Doc Link
https://docs.oracle.com/javase/8/docs/api/java/util/List.html#contains-java.lang.Object-
What we omit to cosider is that even if an equals() method is defined for a class still the hashCode() method is something to care about (even if here you are supposing to compare Strings maybe not?).
Why ?
contains depends on equals and equals works with hashCode to tell if we are talking about the same object here in term of reference.
To resume contains() work on equals-hashCode contract basis
More documentation