I´m writing a simple Program which simulates a graph. This is how i implement a vertex: ( i used the word nodes for neighbours, thats a little confusing maybe..)
public class Vertex {
private String name;
private int nodes;
public Vertex(String name) {
this.name = name;
nodes = 0;
}
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Vertex other = (Vertex) obj;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equalsIgnoreCase(other.name))
return false;
return true;
}
In my Graph class I wrote a method which returns the neighbours(nodes) of a specific vertex:
public List<Vertex> getNodesOf(Vertex v) {
List<Vertex> nodes = new ArrayList<>();
if (vertices.contains(v)) { //vertices is an ArrayList<Vertex>
// adds all neighbours to nodes...
return nodes;
} else {
Terminal.printLine("Error, " + v.getName() + " does not exist here!");
return nodes;
When I call that method from my main method, it works fine:
List<Vertex> nodes = g.getNodesOf(new Vertex(input[1])); //input[1] is a name typed by the user
if (nodes != null) {
for (Vertex node : nodes) {
System.out.println(node.getName());
}
}
But I have another class for the dijkstra-algorithm to find the shortest path. this algorithm also needs the neighbours. this is a part of the code:
Vertex nearest = null;
int distanceInt = 9999;
for (Vertex vertex : unvisited) {
if (distance.containsKey(vertex)) {
if (distance.get(vertex) <= distanceInt) {
nearest = vertex;
distanceInt = distance.get(vertex);
}
}
}
if (graph.getNodesOf(nearest).contains(vertex)) {
// do something...
}
But when i call the method from here, it always says that the ArrayList doesn´t contain the Vertex and the //do something... will never be reached.
I overrided the equals and hashcode method with eclipse, so i thought, this was not the problem.
What´s my mistake?
Your equals()-hashCode()-implementation is broken. The spec says that equal objects must have equal hash-codes. But in your equals()-method you ignore the case of names while the hash-method does not ignore it.
This behaviour is relevant if you use hash-based maps, and distance.containsKey(vertex) looks like a typical map-lookup so I assume that your distance-object is a kind of Map.
Solution: Make your hashCode()-method also case-insensitive, or make your equals()-method case-sensitive.
Related
I am currently looking for an recursive algorithm to find a non key value in my Tree.
I have my Node Class:
public class TreeNode {
private Person person;
private TreeNode left, right;
public TreeNode(Person person) {
this.person = person;
}
public boolean insert(Person person) {
if (person.getAge() < this.person.getAge()){
if (left != null){
return left.insert(person);
}else {
left = new TreeNode(person);
}
}else{
if (right != null){
return right.insert(person);
}else{
right = new TreeNode(person);
}
}
return true;
}
public boolean countryExists(String country){
if (!this.person.getCountry().equals(country)){
if (right != null) {
return right.countryExists(country);
}
if (left != null) {
return left.countryExists(country);
}
}else {
return true;
}
}
}
The Key value here is the age of a person. I want to find out if there is a Person which comes from a specific country. Therefore I made the function countryExists(String country) I don't know how to implement this and I have searched everywhere and watched a lot of videos about post/pre/inorder. The ordering shouldn't be a problem? I have an issue with returning the correct boolean I think...
Thank you for your help.
In your countryExists method you should return false after two != null checks, because if execution came to this point it means that your node doesn't have left and right siblings (it's a leaf) and it's persons's country doesn't equal to the one you're looking for.
But I would suggest doing some refactoring, and instead of negating this.person.getCountry().equals(country), just use it and return true at the beginning of the method.
public boolean countryExists(String country) {
if (this.person.getCountry().equals(country)) {
return true;
}
if (right != null) {
return right.countryExists(country);
}
if (left != null) {
return left.countryExists(country);
}
return false;
}
Also, this is O(n) solution, because you're not using a key to cut off entire branches, and doing full tree traversal.
To make it O(log n) (in the case when the tree is balanced), you need to use country as key and choose only one branch when searching.
I'm using Java 6. I can't figure out why "retainAll" is not correctly computing the intersection of two sets. I have
for (ProductDto dtoProd : dto.getProducts())
{
System.out.println("dtoProd:" + dtoProd.getId());
} // for
for (ProductDto princProd : principal.getProducts())
{
System.out.println("princProd:" + princProd.getId());
} // for
dto.getProducts().retainAll(principal.getProducts());
Despite the fact I observe through my System.out's that I have the same products in both sets, after, the last call, my "dto.getProducts()" is empty. This is the relevant object's id and hashcode methods, if that matters ....
#Override
public int hashCode()
{
return this.id != null ? this.id.hashCode() : 0;
}
#Override
public boolean equals(Object obj)
{
boolean ret = false;
if (obj instanceof ProductDto)
{
final ProductDto other = (ProductDto) obj;
ret = (this.id == other.getId() || (this.id != null && this.id.equals(other.getId())));
}
return ret;
}
and here is the System.out info
dtoProd:777
dtoProd:778
dtoProd:110074257z
princProd:777
princProd:777SB
princProd:110074257z
princProd:110074258z
princProd:110074259z
princProd:6161
princProd:778
What else do I need to do to compute the correct intersection?
I'm trying to compare two lists of same objects, those two lists are nodes_cc and nodes_volume. They contains several Node objects. A Node is defined by ID and VALUE. The nodes on the two lists can have common IDs but not common values.
I want to compare the lists like this: I control the first list list (nodes_cc) , if I meet a node that doesn't appear on the second list (nodes_volume), the control MUST stop, even if I will find other nodes that belong even to the second list. I was thinking to use a break so I tried this:
int count=0;
for (int i=0;i<cc_nodes.size();i++){
Node node = cc_nodes.get(i);
for(int j=0;j<volume_nodes.size();j++){
Node node2 = volume_nodes.get(j);
if (node.id==node2.id){
count++;
}
else {
break;
}
}
}
The problem is: the for cycle breaks only after the first check (count is 1), where i'm doing wrong? Can you help fix me this?
You could use some boolean, and check it after your inner for loop :
int count=0;
for (int i=0;i<cc_nodes.size();i++){
Node node = cc_nodes.get(i);
boolean found = false;
for(int j=0;j<volume_nodes.size();j++){
Node node2 = volume_nodes.get(j);
if (node.id==node2.id){
count++;
found = true;
}
}
if(!found)
break;
}
You can Override .equals() and .hashcode() method in Node object to use id as comparator and then :
int count=0;
for (Node node : cc_nodes){
if(volume_nodes.contains(node))
count++;
else
break;
}
You can add this in Node object (if id is int value)
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + id;
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Node other = (Node) obj;
if (id != other.id)
return false;
return true;
}
I have defined a simple private class named SetOb which contains an int and a Set data structure. I have a HashMap in the 'main' method with SetOb as Key and Integer as value. Now as you can see in the main method, when I feed the HashMap with a SetOb instance and then look for an instance with exactly the same value, it returns 'null'. This has happened with me quite a few times before when I use my own defined data structures like SetOb as Key in HashMap. Can someone please point me what am I missing ?
Please note that in the constructor of SetOb class, I copy the Set passed as argument.
public class Solution {
public static Solution sample = new Solution();
private class SetOb {
public int last;
public Set<Integer> st;
public SetOb(int l , Set<Integer> si ){
last = l;
st = new HashSet<Integer>(si);
}
}
public static void main(String[] args) {
Map<SetOb, Integer> m = new HashMap< SetOb, Integer>();
Set<Integer> a = new HashSet<Integer>();
for(int i =0; i<10; i++){
a.add(i);
}
SetOb x = sample.new SetOb(100, a);
SetOb y = sample.new SetOb(100, a);
m.put(x,500);
Integer val = m.get(y);
if(val!= null) System.out.println("Success: " + val);
else System.out.println("Failure");
}
}
Your x and y are not the same object instances hence contains is not able to match y against x, which ends up not finding the matching key/value in the Map.
If you want the match to succeed, please implement(override) hasCode & equals method in SetOb which will compare the field values.
Sample methods(Eclipse generated) as below:
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + last;
result = prime * result + ((st == null) ? 0 : st.hashCode());
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
SetOb other = (SetOb) obj;
if (last != other.last)
return false;
if (st == null) {
if (other.st != null)
return false;
} else if (!st.equals(other.st))
return false;
return true;
}
The default implementation of hashCode uses object identity to determine the hash code. You will need to implement hashCode (and equals) in your private class if you want value identity. For instance:
private class SetOb {
public int last;
public Set<Integer> st;
public SetOb(int l , Set<Integer> si ){
last = l;
st = new HashSet<Integer>(si);
}
#Override
public boolean equals(Object other) {
if (other.class == SetOb.class) {
SetOb otherSetOb = (SetOb) other;
return otherSetOb.last == last && otherSetOb.st.equals(st);
}
return false;
}
#Override
public int hashCode() {
return 37 * last + st.hashCode();
}
}
SetOb needs to override the hashCode() and thus the equals() methods.
Hash-based collections use these methods to store (hashCode()) and retrieve (hashCode()) and equals()) your objects.
public class state implements Comparator<state>{
Point a;
Point b;
private int path_cost=0;
...
}
class Point {
int x;
int y;
...
}
for above i have:
PriorityQueue<state> openNode= new PriorityQueue<state>();
LinkedList<state> closed =new LinkedList<state>();
state currNode;
I need to check if the Point a of ANY openNode or closed equals currNode's Point a.
I could use contains if i had to match the entire object but here i just care about one variabale (Point a) of state class. I want the method to check all the nodes in PriorityQueue and LinkedList.
addition:
I am thinking about using Iterator on my priorityQueue and LinkedList. But i am not sure how to read the value of Point a using Iterator.
EDIT: Looked like I'd misunderstood slightly. It's simpler than I thought.
// I've assumed more conventional names
Point currPoint = currNode.getPointA();
for (State openNode : openNodes) {
if (openNode.getPointA().equals(currPoint)) {
return true;
}
}
for (State closedNode : closedNodes) {
if (closedNode.getPointA().equals(currPoint)) {
return true;
}
}
// No matching points
return false;
You could potentially use Guava's Iterables.concat() method to make this slightly simpler:
for (State node : Iterables.concat(closedNodes, openNodes)) {
if (node.getPointA().equals(currPoint)) {
return true;
}
}
return false;
If you need to know which node has an equal point A, just change it to:
for (State node : Iterables.concat(closedNodes, openNodes)) {
if (node.getPointA().equals(currPoint)) {
return node;
}
}
return null;
That will only find one such node, of course - there may be multiple matches.
You will have to either provide equals method on Point a for state class or just use simple iteration and iterate over both List for comparison. contains method does the same.
If you use any other method it will be time consuming.
Very odd method is use Comparator to check equality
class PointAComparator implements Comparator<State>
{
Point p = null;
public PointAComparator(Point a) {
p = a;
}
#Override
public int compare(State o1, State o2) {
return (p.x == o1.a.x && p.y == o1.a.y) ? 1
: (p.x == o2.a.x && p.y == o2.a.y) ? 1 : -1;
}
}
Above compare method returns 1 for equal else -1 so when you do sorting then each list will have elements at the start which are equal. and then you can check for first element.
i used method overriding on function equals for both the object and achieved my result.
class Point {
int x;
int y;
...
#Override
public boolean equals(Object other){
if (other == null) return false;
if (other == this) return true;
if (!(other instanceof Point))return false;
Point otherPoint = (Point)other;
return (this.x==otherPoint.getX() && this.y==otherPoint.getY() )? true : false;
}
}
public class state implements Comparator<state>{
Point a;
Point b;
private int path_cost=0;
...
#Override
public boolean equals(Object other){
if (other == null) return false;
if (other == this) return true;
if (!(other instanceof state))return false;
state otherState = (state)other;
return ((this.a).equals(otherState.a))? true : false;
}
}