I implemented the equal’s method in my Person object with the #annotation, however, when I create an object in my main class and check it against my List of Person objects, it doesn’t return the correct index. It says they are both at 1, but it should be 1 and 3.
Objective:
Check to see if “Andy Bernard” exists in my list and if so, display the index of the objects.
import java.util.ArrayList;
import java.util.List;
public class Person {
private String firstName;
private String lastName;
public Person(String firstName,String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
#Override
public String toString() {
return String.format(this.firstName + " " + this.lastName);
}
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result
+ ((firstName == null) ? 0 : firstName.hashCode());
result = prime * result
+ ((lastName == null) ? 0 : lastName.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;
Person other = (Person) obj;
if (firstName == null) {
if (other.firstName != null)
return false;
} else if (!firstName.equals(other.firstName))
return false;
if (lastName == null) {
if (other.lastName != null)
return false;
} else if (!lastName.equals(other.lastName))
return false;
return true;
}
private static List<Person> deletePeople = new ArrayList<>();
public static void main(String[] args) {
addPerson("Micheal","Scott");
addPerson("Andy","Bernard");
addPerson("Micheal","Scott");
addPerson("Andy","Bernard");
display();
}
public static void addPerson(String firstname, String lastname) {
Person createPerson = new Person(firstname,lastname);
deletePeople.add(createPerson);
}
public static void display() {
Person checkPerson = new Person("Andy","Bernard");
for (Person display : deletePeople) {
if(display.equals(checkPerson)) {
System.out.println((display.getFirstName() + " " +
display.getLastName() + " " + deletePeople.indexOf(display)));
}
}
}
}
indexOf returns the index of the first occurence which is the same (according to the equals method) in the List. That's why you see both 1 printed.
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.
And you can see the implementation (for ArrayList, but that's the same idea for a LinkedList except that you iterate other the nodes):
229 public int indexOf(Object o) {
230 if (o == null) {
231 for (int i = 0; i < size; i++)
232 if (elementData[i]==null)
233 return i;
234 } else {
235 for (int i = 0; i < size; i++)
236 if (o.equals(elementData[i]))
237 return i;
238 }
239 return -1;
240 }
If you want to print the index associated, you can use a counter that you increment at each iteration.
int index = 0;
for (Person display : deletePeople) {
if(display.equals(checkPerson)){
System.out.println((display.getFirstName() + " " + display.getLastName() + " " + index));
}
index++;
}
It would also be possible with a standard for loop.
for(int i = 0; i < deletePeople.size(); i++){
Person display = deletePeople.get(i);
if(display.equals(checkPerson)){
System.out.println((display.getFirstName() + " " + display.getLastName() + " " + i));
}
}
However be careful with the latter implementation because if the underlying representation of the list is a LinkedList the complexity of the above loop would be O(n^2) instead of O(n).
By calling indexOf() you print the first index that matches, rather than the current index. If you're interested in tracking your position in the list, the best thing is to do that manually, so instead of a for-each loop:
for(Object o : ls) {
// the syntax is nice, but we don't have an easy way to
// tell how far into the list we are
System.out.println(o);
}
Instead, use a simple for loop:
for(int i = 0; i < ls.size(); i++) {
Object o = ls.get(i);
// Now we have access to the object *and* its index
System.out.println(i+": "+o);
}
Additionally, there's quite a few simple cleanups you could make in your code, if you'll forgive me, here's some suggestions:
Avoid allowing null in your objects - rarely is null actually meaningful, and allowing it forces all calling code to do null checks everywhere.
public Person(String firstName,String lastName) {
if(firstName == null || lastName == null) {
throw new NullPointerException("First/Last name cannot be null");
}
this.firstName = firstName;
this.lastName = lastName;
}
Use String.format() correctly, or just avoid it. Your current toString() method calls String.format(this.firstName + " " + this.lastName), which doesn't actually do anything; you might as well just return the concatenated string without String.format(). Alternatively, you can properly use the format functionality like so:
String.format("%s %s", firstName, lastName);
Take advantage of Java 7's Objects class for your hashCode() and equals() methods:
#Override
public int hashCode() {
return Objects.hash(firstName, lastName);
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Person other = (Person) obj;
return Objects.equals(firstName, other.firstName) &&
Objects.equals(lastName, other.lastName);
}
Related
package restaurantclient;
public class Restaurant extends Store {
//Instance Variables
private int peopleServed;
private double averagePrice;
//Constructor with 3 parameters
public Restaurant(String storename, int peopleServed, double averagePrice) {
super(storename);
setPeopleServed(peopleServed);
setAveragePrice(averagePrice);
}
//Getters (Accessors)
public int getPeopleServed() {
return peopleServed;
}
public double getAveragePrice() {
return averagePrice;
}
//Setters (Mutators)
public void setPeopleServed(int peopleServed) {
this.peopleServed = peopleServed;
}
public void setAveragePrice(double averagePrice) {
this.averagePrice = averagePrice;
}
//toString Method [Must Override]
#Override
public String toString() {
String information = "Store name: " + (super.getName());
information += "\n" + "The number of people served: " + peopleServed;
information += "\n" + "The average price per person: $" + averagePrice;
return information;
}
//Equals Method
#Override
public boolean equals (Object other) {
if (this == other)
return true;
if (other == null)
return false;
if (!(other instanceof Restaurant))
return false;
Restaurant otherRestaurant = (Restaurant) other;
if (this.getName() == null) {
if (otherRestaurant.getName() != null)
return false;
} else if (!(this.getName().equals(otherRestaurant.getName())))
return false;
if (peopleServed == -1) {
if (otherRestaurant.peopleServed != -1)
return false;
} else if (peopleServed != (otherRestaurant.peopleServed))
return false;
if (averagePrice == -1) {
if (otherRestaurant.averagePrice != -1)
return false;
}
else if (averagePrice != (otherRestaurant.averagePrice))
return false;
return true;
}
public double getAverageTaxes() {
double total;
total = this.getPeopleServed() * this.getAveragePrice()
* super.CA_TAX_RATE;
return total;
}
}
package restaurantclient;
public class Store {
//Instance Variables
protected final double CA_TAX_RATE = 0.0884;
private String storename;
//Constructor
public Store(String storename) {
setName(storename);
}
//Getters (Accessors)
public String getName() {
return storename;
}
//Setters (Mutators)
public void setName(String storename) {
this.storename = storename;
}
//toString Method [Must Override]
#Override
public String toString() {
String directory = "Name of store: " + storename;
return directory;
}
//Equals Method
public boolean equals (Store storename) {
if (this == storename)
return true;
if (storename == null)
return false;
if (!(storename instanceof Store))
return false;
return true;
}
}
Above are the equals methods I'm calling. They are displaying the wrong answers: it should be in the first instance, "They are not equal" and in the second instance after setting everything equal to each other, it should display, "They are equal". I have tried very hard on this problem and many things have not worked. There are no overt errors it runs fine, but I am doing something wrong and some precise guidance would be a lot of help. Much of the vague hints have got me nowhere. I need something concrete, if this makes to you. Thanks again for the help. The following is the Client class:
package restaurantclient;
public class RestaurantClient {
public static void main(String[] args) {
Restaurant r1 = new Restaurant("McDonald's", 1000000, 8.00);
Restaurant r2 = new Restaurant("KFC", 500000, 6.00);
System.out.println(r1.toString());
System.out.println(r2.toString());
System.out.println();
r2.setAveragePrice(r1.getAveragePrice());
r2.setPeopleServed(r1.getPeopleServed());
System.out.println(r1.toString());
System.out.println(r2.toString());
if (r1.equals(r2)) {
System.out.println("The objects are equal.");
}
else {
System.out.println("The objects are not equal."); //SHOULD say "not equal" here EVERY TIME the second instance (next comment down) says "Equal"...this should never change.
System.out.println();
}
System.out.println();
r2.setName(r1.getName());
System.out.println(r1.toString());
System.out.println(r2.toString());
if (r1.equals(r2)) {
System.out.println("The objects are equal."); //Now that everything is equal, it should print "The Objects are Equal" but it doesn't. It's in lock-step with the previous instance. Changing some things like return true to return false might make both these instances "Are equal" and some might change them to "Not Equal" but they are never the way I want them, which is when 2 changes are made, they are not equal (first case) and when the third and final change is made (like this case here on this line) it should say "the obj are equal" but it doesn't.
}
else {
System.out.println("The objects are not equal.");
System.out.println();
}
System.out.println();
System.out.print("The avg. annual taxes paid by the restaurant is: $");
System.out.println(r1.getAverageTaxes());
}
}
The reason that I see is simple, you are not getting the same name.
In equals, you are comparing super.getName() with otherRestaurant.getName()
If the superclass of Restaurant have a different format or return an other variable, since you compare it to Restaurant.getName(), this will compare different value. Using this.getName() to compare the same variable (or format of variable) is safer. Even if Restaurant.getName() is only returning the super.getName(), this would be safer if you changed the method of Restaurant (because you prefer it an other way).
Here is an example :
Restaurant:
public String getName(){
return "A restaurant " + name;
}
Super class :
public String getName(){
return name;
}
Will result into comparing "A restaurant : KFC" with "KFV".
Using the same getter assure you to return the same "format".
Aslo, your logic is wrong. You want to check if one of the value is different, if it is, return false. And if you reach the end of the method, meaning there where no difference leading to a return false, you return true.
if (this.getName() == null) {
if (otherRestaurant.getName() != null)
return false;
} else if (!super.getName().equals(otherRestaurant.getName())) // added ! here
return false;
if (peopleServed == -1) {
if (otherRestaurant.peopleServed != -1)
return false;
} else if (peopleServed != (otherRestaurant.peopleServed)) // change to != here
return false;
if (averagePrice == -1) {
if (otherRestaurant.averagePrice != -1)
return false;
}
else if (averagePrice != (otherRestaurant.averagePrice)) // change to != here
return false;
//No differences, then it is equals.
return true;
Note :
This condition could be shorten
if (averagePrice == -1) {
if (otherRestaurant.averagePrice != -1)
return false;
}
else if (averagePrice != (otherRestaurant.averagePrice)) // change to != here
return false;
Since it is doing the same thing (comparing the values) :
if (averagePrice != (otherRestaurant.averagePrice))
return false;
Edit :
You are having a problem of overriding.
In Store:
public boolean equals(Store s){}
And in Restaurant
public boolean equals(Object o){}
Since you are calling the method with a Restaurant (subclass of Store), the JVM will use the Store.equals method since it match the type, Restaurant.equals is not overriding it, it override the method in Object. Change to Store.equals(Object o) to correct this.
The method equals comes from Object so it should be always receiving an Object to prevent any problem like this one, if you specify the type in a method, it will not override correctly the method (depending on the type)
Seems you are checking for equality and then returning false, when you should check for not equality to return false.
else if (!super.getName().equals(otherRestaurant.getName()))
return false;
else if (peopleServed != (otherRestaurant.peopleServed))
return false;
else if (averagePrice != (otherRestaurant.averagePrice))
return false;
Also as asked, any reason to uses super.getName() ?
And since peopleServed & averagePrice cannot be null, the -1 check is not needed as the expected result we be the same as the equality check
And finally, I'm guessing the end return should be true, as it means it's different instance of an object, but they have all the same attributs.
Within your equals() method , If super.name() equals otherRestaurant.name() shouldn't you return true, here:
else if (super.getName().equals(otherRestaurant.getName())) return false;
Ok, that one will work in any cases:
#Override
public boolean equals (Object other) {
if (this == other)
return true;
if (other == null)
return false;
if (!(other instanceof Restaurant))
return false;
Restaurant otherRestaurant = (Restaurant) other;
if (name == null) {
if (otherRestaurant.getName() != null)
return false;
} else if (name!=otherRestaurant.getName())
return false;
if (peopleServed == -1) {
if (otherRestaurant.peopleServed != -1)
return false;
} else if (peopleServed != otherRestaurant.peopleServed)
return false;
if (averagePrice == -1) {
if (otherRestaurant.averagePrice != -1)
return false;
}
else if (averagePrice != otherRestaurant.averagePrice)
return false;
return true;
}
check it and reply if it is ok
private List<String> values = new ArrayList<String>();
public WhitespaceEqualsTest() {
values.add("I ");
values.add("I");
values.add(". ");
values.add(".");
values.add("1");
values.add("1 ");
System.out.println(refine(values));
}
private List<String> refine(List<String> input){
ArrayList<String> outerLoopValues = (ArrayList<String>) input;
ArrayList<String> innerLoopValues = (ArrayList<String>) input;
ArrayList<String> results = new ArrayList<String>();
for(String string1 : outerLoopValues){
for(String string2 : innerLoopValues){
if(string1.contains(string2) == false){
results.add(string1);
}
}
}
Set<String> temp = new HashSet<String>();
temp.addAll(results);
results.clear();
results.addAll(temp);
return results;
}
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((values == null) ? 0 : values.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;
WhitespaceEqualsTest other = (WhitespaceEqualsTest) obj;
if (values == null) {
if (other.values != null)
return false;
} else if (!values.equals(other.values))
return false;
return true;
}
I've overriden the hashCode() and equals(), so I'm not really sure what's wrong. They are generated using Eclipse (Source -> Generate hashCode() and equals()). Why isn't it detecting that the same character without a space is contained within a character with a space? The output is:
[1, . , I , I, ., 1 ]
As mentioned in one of the comments, you should be using a String wrapper to wrap the strings and override the equals and hashcode methods.
My solution is based on the assumption that "I " should be equals to "I", hence only one of them should be added into the result.
However I'll need to addon that based on the documentation in Java Objects
and Java Arraylist with regards to equals and contains implementation respectively. The hashcode method would have to return a common value. I've written the explanation in the code as comments. Let me know if there are any issues.
Main Class
public class StackOverflowMain
{
private static List<String> values = new ArrayList<String>();
public static void main(String[] args) {
values.add("I ");
values.add("I");
values.add(". ");
values.add(".");
values.add("1");
values.add("1 ");
List<WhitespaceEqualsTest> toRefineList = new ArrayList<WhitespaceEqualsTest>();
for (String value : values) {
toRefineList.add(new WhitespaceEqualsTest(value));
}
System.out.println(refine(toRefineList));
}
private static List<WhitespaceEqualsTest> refine(List<WhitespaceEqualsTest> input) {
ArrayList<WhitespaceEqualsTest> loopValues = (ArrayList<WhitespaceEqualsTest>) input;
ArrayList<WhitespaceEqualsTest> results = new ArrayList<WhitespaceEqualsTest>();
for (WhitespaceEqualsTest value : loopValues) {
if (!results.contains(loopValues)) {
results.add(value);
}
}
Set<WhitespaceEqualsTest> temp = new HashSet<WhitespaceEqualsTest>();
temp.addAll(results);
results.clear();
results.addAll(temp);
return results;
}
}
Inner WhitespaceEqualsTest Class
class WhitespaceEqualsTest {
private String value;
public WhitespaceEqualsTest(String value) {
this.value = value;
}
public void setString(String value) {
this.value = value;
}
public String getString() {
return this.value;
}
public int hashCode() {
/*
* Arraylist.contains is evaluated by using (o==null ? e==null : o.equals(e)) as mentioned in the javadoc
* and Object.equals() would evaluate using hashcode() first to check if the object o is equal to object e
* before calling .equals() method to evaluate.
*
* As mentioned in java doc at http://docs.oracle.com/javase/7/docs/api/java/util/Collection.html#equals(java.lang.Object)
* c1.equals(c2) implies that c1.hashCode()==c2.hashCode() should be satisfied
* which is not in this question
*/
return 0;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
WhitespaceEqualsTest other = (WhitespaceEqualsTest) obj;
if (value == null) {
if (other.value != null)
return false;
} else if (!value.contains(other.value) && !other.value.contains(value)){
/*
* Does a checking on both ends since "I " contains "I" but "I" does not contain "I " due to the whitespace
* For this question, if one of the condition satisfy it should be equal
*/
return false;
}
return true;
}
#Override
public String toString() {
return this.value;
}
}
Result
[I , . , 1]
String class is final. So you cannot override its equals and hashCode methods.
private List<StringWrapper> values = new ArrayList<StringWrapper>();
public WhitespaceEqualsTest() {
values.add(new StringWrapper("I "));
values.add(new StringWrapper("I"));
values.add(new StringWrapper(". "));
values.add(new StringWrapper("."));
values.add(new StringWrapper("1"));
values.add(new StringWrapper("1 "));
System.out.println(refine(values));
}
private List<StringWrapper> refine(List<StringWrapper> input){
//no need to iterate the list
//the set will automatically cancel out the duplicate
Set<StringWrapper> temp = new HashSet<StringWrapper>(input);
ArrayList<StringWrapper> results = new ArrayList<StringWrapper>();
results.addAll(temp);
return results;
}
Create a wrapper class of String then override the equals and hashcode method.
class StringWrapper {
private String value;
public StringWrapper(String value){
this.value = value;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
#Override
public String toString(){
return value;
}
#Override
public boolean equals(Object obj){
boolean result = Boolean.FALSE;
if(obj != null && obj instanceof StringWrapper){
StringWrapper stringWrapper = (StringWrapper) obj;
result = value.trim().equals(stringWrapper.getValue().trim());
}
return result;
}
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((value.trim() == null) ? 0 : value.trim().hashCode());
return result;
}
}
You add the values to a Set. In a Set in any case a value occurs once - hence it is a set. ;)
You might as well modify the loop to see what happens
for(String string1 : outerLoopValues){
for(String string2 : innerLoopValues){
if(string1.contains(string2) == false){
results.add(string1);
System.out.println("added \"" + string1 + "\" since it does not contain \"" + string2 + "\"");
}
}
}
Giving the following output:
added "I " since it does not contain ". "
added "I " since it does not contain "."
added "I " since it does not contain "1"
added "I " since it does not contain "1 "
added "I" since it does not contain "I "
added "I" since it does not contain ". "
added "I" since it does not contain "."
added "I" since it does not contain "1"
added "I" since it does not contain "1 "
......
[1, . , I , I, ., 1 ]
To add them if they do not contain each other is the idea i guess?
Then pushing the List through a Set removes the duplicates! See here: Does adding a duplicate value to a HashSet/HashMap replace the previous value
Changing the condition in the Loop from false to true yields this (no change after using the Set/HashSet in the last line of output!)
added "I " since it does contain "I "
added "I " since it does contain "I"
added "I" since it does contain "I"
added ". " since it does contain ". "
added ". " since it does contain "."
added "." since it does contain "."
added "1" since it does contain "1"
added "1 " since it does contain "1"
added "1 " since it does contain "1 "
[1, . , I , I, ., 1 ]
Which answers your question: It does detect if e.g. "I " contains "I".
System.out.println("I ".contains("I"));
says "true"
Hope this helps ^^-d
I have a flat data that represent the hierarchical relationship as below:
ID Name PID
0 A NULL
1 B 0
2 C 0
4 D 1
5 E 1
6 F 4
3 G 0
This table represents the 'data table', where PID indicates the parent element.
For example, in the first row we see that A has PID null whereas B has PID 0, which means that B’s parent is A, because 0 is the ID of A, and A is the root element, because it does not have a PID. Similarly, C has parent A because C too has PID 0, and 0 is the ID of A.
I create a class RecordHolder to represent the above table. I also implement the method processRecordHolder
public Map<String, List<String>> processRecordHolder()
The returned map uses element as keys, and holds collections of descendant nodes as values. For example, the first item in the map corresponds to element A, which has many descendants, whereas element C has no descendant. The order of members in the output is not important.
public static void main(String[] args) {
RecordHolder dt = new RecordHolder();
dt.addRow(0, "A", null);
dt.addRow(1, "B", 0);
dt.addRow(2, "C", 0);
dt.addRow(4, "D", 1);
dt.addRow(5, "E", 1);
dt.addRow(6, "F", 4);
dt.addRow(3, "G", 0);
System.out.println("Output:");
System.out.println(dt.processRecordHolder());
}
Output:
{D=[F], A=[B, C, G, D, E, F], B=[D, E, F]}
or
{D=[F], E=null, F=null, G=null, A=[B, C, G, D, E, F], B=[D, E, F], C=null}
Below is my implementation of Record which I am able to come up so far:
public class Record {
public Integer id;
public String name;
public Integer parentId;
public Record parent;
public Collection<Record> children;
public Record(Integer id, String name, Integer parentId) {
this();
this.id = id;
this.name = name;
this.parentId = parentId;
}
public Record() {
children = Collections.newSetFromMap(new ConcurrentHashMap<Record, Boolean>())
}
public Collection<Record> getChildren() {
return children;
}
public Record getParent() {
return parent;
}
public Integer getParentId() {
return parentId;
}
#Override
public String toString() {
return "Record{" + "id=" + id + ", name=" + name + ", parentId=" + parentId + '}';
}
/* (non-Javadoc)
* #see java.lang.Object#hashCode()
*/
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((id == null) ? 0 : id.hashCode());
result = prime * result + ((name == null) ? 0 : name.hashCode());
result = prime * result + ((parentId == null) ? 0 : parentId.hashCode());
return result;
}
/* (non-Javadoc)
* #see java.lang.Object#equals(java.lang.Object)
*/
#Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (!(obj instanceof Record)) {
return false;
}
Record other = (Record) obj;
if (id == null) {
if (other.id != null) {
return false;
}
} else if (!id.equals(other.id)) {
return false;
}
if (name == null) {
if (other.name != null) {
return false;
}
} else if (!name.equals(other.name)) {
return false;
}
if (parentId == null) {
if (other.parentId != null) {
return false;
}
} else if (!parentId.equals(other.parentId)) {
return false;
}
return true;
}
}
Now I am not able to understand other step what should I do?
Try:
public class RecordHolder {
Map<Integer,String> namesById = new HashMap<>();
Map<Integer,List<Integer>> childrenById = new HashMap<>();
public void addRow(Integer id, String name, Integer parent) {
namesById.put(id, name);
List<Integer> children = childrenById.get(parent);
if (children == null) {
children = new ArrayList<>();
childrenById.put(parent, children);
}
children.add(id);
}
public Map<String,List<String>> processRecordHolder() {
Map<String,List<String>> results = new HashMap<>();
descendants(null, results);
return results;
}
private List<String> descendants(Integer id, Map<String, List<String>> results) {
final List<String> childrenNames = new ArrayList<>();
final List<Integer> childrenIds = childrenById.get(id);
if (childrenIds != null && childrenIds.size() > 0) {
for (Integer childrenId : childrenIds) {
final String childName = namesById.get(childrenId);
childrenNames.add(childName);
final List<String> grandchildrenNames = descendants(childrenId, results);
childrenNames.addAll(grandchildrenNames);
}
if (id != null) {
results.put(namesById.get(id), childrenNames);
}
}
return childrenNames;
}
}
Just in case you'd like to try my simpler idea for implementation, here it is in brief detail. This way, you can decide whether you want to use your current idea or try to start over using this idea. (note the code below is presented as a pseudo-Java outline, it won't compile and is not tested):
int numNodes = 7;
Node[] nodes = new Node[numNodes];
//Read in your file here using a Scanner/FileReader or something
int ID = 0;
char value = 0;
int PID = 0;
while(scanner.hasNextLine()){
ID = scan.next();
value = scan.next();
PID = scan.next();
nodes[ID] = new Node(value, PID);
}
And then a node class:
class Node{
char value;
Node parent;
public Node(value, parentID){
this.value = value;
if(parentID == -1)
parent = null;
else
parent = nodes[parentID]; //nodes will have to be a global array or get passed to the constructor
}
}
Note that this constructor will only work if the item in nodes[parentID] has been initialized previously. (This is the case for your current input file order, but might not be in other situations.)
Ancestry:
To find the ancestry of a node using ID with this approach simply do:
printAncestry(nodes[ID]);
void printAncestry(Node n){
System.out.println("Child: " + n.value);
System.out.println("Ancestry: ");
while(n.parent != null){
n = n.parent;
System.out.println(n.value);
}
}
Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 7 years ago.
Improve this question
public class Variable implements Comparable<Variable> {
String name;
String type;
public Variable(String name, String type){
this.name = name;
this.type = type;
}
public String getName(){
return name;
}
public String getType(){
return type;
}
public boolean equals(Object o){
if(o != null && (o instanceof Variable)) {
return ((Variable)o).getName().equals(name) &&
((Variable)o).getType().equals(type);
}
return false;
}
public int compareTo(Variable v){
if (type.compareTo(v.type) != 0) return type.compareTo(v.type);
return name.compareTo(v.name);
}
public String toString(){
return type+" "+name;
}
}
public class Operation implements Comparable<Operation>{
String name;
String type;
List<Variable> arguments;
public Operation(String name, String type){
this.name = name;
this.type = type;
arguments = new ArrayList<Variable>();
}
public void addArgument(Variable a){
arguments.add(a);
}
public String getName(){
return name;
}
public String getType(){
return type;
}
public List<Variable> getArguments(){
return arguments;
}
public int getArgumentNumber(){
return arguments.size();
}
public boolean equals(Object o){
if(o != null && (o instanceof Operation)) {
List<Variable> oa = ((Operation)o).getArguments();
Collection.sort(arguments);
Collection.sort(oa);
return ((Operation)o).getName().equals(name) &&
((Operation)o).getType().equals(type) &&
((Operation)o).getArguments().equals(arguments);
}
return false;
}
public int compareTo(Operation v){
if (type.compareTo(v.type) != 0) return type.compareTo(v.type);
else if(name.compareTo(v.name) != 0) return name.compareTo(v.name);
else{
if (arguments.size() < v.getArgumentNumber()) return -1;
else if(arguments.size() > v.getArgumentNumber()) return 1;
else
}
}
public String toString(){
String s = "";
if (arguments.isEmpty()) return type + " " + name + "(" + ")";
else {
for(Variable v:arguments){
s+= v.type + " ";
}
}
return type + " " + name + "(" + s.trim() + ")";
}
}
As you can see, in the equals function of Operation class
public boolean equals(Object o){
if(o != null && (o instanceof Operation)) {
List<Variable> oa = ((Operation)o).getArguments();
Collection.sort(arguments);
Collection.sort(oa);
return ((Operation)o).getName().equals(name) &&
((Operation)o).getType().equals(type) &&
((Operation)o).getArguments().equals(arguments);
}
return false;
}
I try to sort the list of Variable, but it give me error message "The method sort(List) is undefined for the type Collection", but I have already defined compareTo function in Variable class.
PS. anyone have idea that how should i define compareTo function in Operation class, should i sort first arguments and then compareTo each Variable?
Thanks.
You're using the wrong class to sort. Collection.sort does not exist, while Collections.sort does.
public boolean equals(Object o){
if(o != null && (o instanceof Operation)) {
List<Variable> oa = ((Operation)o).getArguments();
Collections.sort(arguments);
Collections.sort(oa);
return ((Operation)o).getName().equals(name) &&
((Operation)o).getType().equals(type) &&
((Operation)o).getArguments().equals(arguments);
}
return false;
}
Collections, as in plural, with an 's'.
http://docs.oracle.com/javase/8/docs/api/java/util/Collections.html#method.summary
PS. anyone have idea that how should i define compareTo function in
Operation class, should i sort first arguments and then compareTo each
Variable?
Since you rely on the order of arguments in your Operation class consider to store the Variables in arguments in a sorted order already.
This means eiter sort the List with every new added Variable or use a Set instead of the List. So you don't have to sort in your equals and compareTo methods.
To your question regarding the compareTo method:
if the size of arguments is the same iterate over both arguments lists comparing the same indices of the Variables via compareTo and return the first result which is != 0. (Or '0' if all elements are equal)
One possible solution:
public int compareTo(Operation v) {
int res = type.compareTo(v.type);
if (res != 0) return res;
res = name.compareTo(v.name);
if (res != 0) return res;
if (arguments.size() != v.arguments.size()) return arguments.size() - v.arguments.size();
for (int i = 0; i < arguments.size(); ++i) {
res = arguments.get(i).compareTo(v.arguments.get(i));
if (res != 0) return res;
}
return 0;
}
I have developed a pojo named Employee.java. Now I was planning to make it as user defined collection. I want to make a map and store all the employee type objects in it.
Below is my pojo
public class Employee {
String name,job;
int salary;
public Employee(String n , String j, int t ) //constructor
{
this.name= n;
this.job=j;
this.salary= t;
}
#Override
public int hashCode()
{
return name.hashCode()+job.hashCode()+salary;
}
#Override
public boolean equals(Object obj) {
Employee e = (Employee) obj;
return this.name.equals(e.name)&&this.job.equals(e.job)&&this.salary==e.salary;
}
}
Now I have developed another class that contains map and will store employee type objects..
public static void main(String[] args)
{
Map employeeMap = new HashMap();
Employee e = new Employee("Saral", "Trainer", 34000);
Employee e1 = new Employee("Sarall", "saral", 34090);
employeeMap.put("S", e);
employeeMap.put("S1", e);
System.out.println(employeeMap.size());
Set s = employeeMap.entrySet();
Iterator it = s.iterator();
while(it.hasNext())
{
Map.Entry m =(Map.Entry)it.next();
System.out.println(m.getKey()+"\t"+m.getValue());
}
but when I try to run it , I want to fetch the employee details but I GET DISPLAYED THE OBJECT ON SCREEN ...I want to see the employees value, Please advise me how to get values from employee object.
2
S CollectionsPrac.Employee#285c2854
S1 CollectionsPrac.Employee#285c2854
You need to override the toString method in your Employee class, for example:
public String toString() {
return name + " [" + job + "] - salary: " + salary;
}
By the way, you can replace:
Iterator it = s.iterator();
while(it.hasNext())
{
Map.Entry m =(Map.Entry)it.next();
System.out.println(m.getKey()+"\t"+m.getValue());
}
with
System.out.println(s.toString());
Unless you really want the output to be tab separated.
You need to override the toString() method of Employee
#Override pulic String toString() {
return name + " " + job;
}
First of all. Your hashcode is broken.
Try running this:
System.out.println("Should be false: " + (new Employee("Sara", "Trainer", 1).hashCode() == new Employee("Trainer", "Sara", 1).hashCode()));
If you are using and IDE (like eclipse) there is a function to generate equals and hashcode methods automatically and you would get something like this:
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((job == null) ? 0 : job.hashCode());
result = prime * result + ((name == null) ? 0 : name.hashCode());
result = prime * result + salary;
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Employee other = (Employee) obj;
if (job == null) {
if (other.job != null)
return false;
} else if (!job.equals(other.job))
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
if (salary != other.salary)
return false;
return true;
}
As for your main method.. You should try to learn some basics about generics (the stuff inside the <>). You don't need the nity grity details at first. Just learn how to use it with lists and maps.. It will make your life a lot easier. Especially since your using and IDE...
Here is a refactored version of your main method:
public static void main(String[] args)
{
Map<String, Employee> employeeMap = new HashMap<String, Employee>();
Employee e = new Employee("Saral", "Trainer", 34000);
Employee e1 = new Employee("Sarall", "saral", 34090);
employeeMap.put("S", e);
employeeMap.put("S1", e1);
System.out.println(employeeMap.size());
Set<Entry<String, Employee>> entrySet = employeeMap.entrySet();
for (Entry<String, Employee> entry: entrySet) {
System.out.println(entry.getKey()+"\t"+entry.getValue().name);
}
System.out.println("Should be false: " + (new Employee("Sara", "Trainer", 1).hashCode() == new Employee("Trainer", "Sara", 1).hashCode()));
}
Change this in
Iterator it = s.iterator();
while(it.hasNext())
{
Map.Entry m =(Map.Entry)it.next();
Employee empl = (Employee) m.getValue();
System.out.println(m.getKey()+"\t"+empl.name);
}
As you can see with the line
Employee empl = (Employee) m.getValue();
the value is "casted" to an Employee object, and you can start to work with empl variable and use all the Employee class methods and members.