I have little problem with java. i am not able to get accurate result.
what's wrong with this code please help me out from this code
your own objects as keys in Maps or in Sets. To use your own objects as keys in Maps or in Sets.code not executing correctly..
what is use of hashcode and equals in java.
Code:
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;
class Person {
private int id;
private String name;
public Person(int id, String name) {
this.id = id;
this.name = name;
}
public String toString() {
return "{ID is: " + id + "; name is: " + name + "}";
}
}
public class App {
public static void main(String[] args) {
//creating person object
Person p1 = new Person(0, "Bob");
Person p2 = new Person(1, "Sue");
Person p3 = new Person(2, "Mike");
Person p4 = new Person(1, "Sue");
Map<Person, Integer> map = new LinkedHashMap<Person, Integer>();
//putting on map
map.put(p1, 1);
map.put(p2, 2);
map.put(p3, 3);
map.put(p4, 1);
//displaying the result
for(Person key: map.keySet()) {
System.out.println(key + ": " + map.get(key));
}
//using set
Set<Person> set = new LinkedHashSet<Person>();
//adding on set
set.add(p1);
set.add(p2);
set.add(p3);
set.add(p4);
//displaying the result
System.out.println(set);
}
}
Expected Output:
{ID is: 0; name is: Bob}: 1
{ID is: 1; name is: Sue}: 1
{ID is: 2; name is: Mike}: 3
[{ID is: 0; name is: Bob}, {ID is: 1; name is: Sue}, {ID is: 2; name is: Mike}]
The equals() and hashCode() methods are both implemented in the superclass Object.
In real worl applications, you may incounter the need to override both of these methods but don't do unless you understand their utility. I'll try to give the best in short:
equals() method is used for equivalence relations.
hashCode() is used to provide, as it reveals, a hash code which is a 32-byte representation of the object.
Imagine that you have a class Person with below declaration:
public class Person {
public int nationalIdentityNumber;
public String firstName;
public String secondName;
public Person (int nationalIdentityNumber, String firstName, String secondName) {
this.nationalIdentityNumber = nationalIdentityNumber;
this.firstName = firstName;
this.secondName = secondName;
}
}
When not overriding the equals() methods:
Person p1 = new Person(1234,"Jhon","Legend");
Person p1 = new Person(1234,"Mary","Richard");
When we call p1.equals(p2) this will result in a false result thus the default method from Object class compares the objects references. But what I actually you may need is that two Persons are considered equals when their nationalIdentityNumber instance variable is equal so you need to override the equals() implementation as below:
#Override
public boolean equals(Object object) {
boolean result = false;
if (object == null || object.getClass() != getClass()) {
result = false;
} else {
Person person = (Person) object;
if (this.nationalIdentityNumber == person.nationalIdentityNumber) {
result = true;
}
}
return result;
}
So p1.equals(p2) will now return a true result.
Now back to hashCode, imagine you are registering your Person objects in a HashSet
HashSet<Person> personsHS = new HashSet<Person>();
personsHS.add(p1);
personsHS.add(p2);
When invoquing
System.out.println("personsHS.contains( new Person(1234,Jhon,Legend))--->>>"+personsHS.contains(new Person(1234,"Jhon","Legend")));
it will result in personsHS.contains( new Person(1234,"Jhon","Legend"))--->>>false statement because the HashSet is using the default Object#hashCode() method to determine the equality of keys thus we need to override it to ensure the Person uniqueness (based on your requirements) inside the hashtables:
#Override
public int hashCode() {
return this.nationalIdentityNumber;
}
So that
System.out.println("personsHS.contains(new Person(1234,Jhon,Legend))--->>>"+personsHS.contains(new Person(1234,"Jhon","Legend")));
will result in personsHS.contains( new Person(1234,"Jhon","Legend"))--->>>true
This is a simplest that it could be but note that it will always depend on your application and your own objects to wether or not to override this methods and which fashion to do so.
BR.
Cfr the general contract for hashCode:
If two objects are equal according to the equals(Object) method, then
calling the hashCode method on each of the two objects must produce
the same integer result.
In java, to use your own objects in some fonctionnalities you sometimes need to create some "generic" fonctions. HashCode and Equals for instance.
To use your objects in a hashmap like you are doing, java needs those. So you have to implement them in your "person" class. Here is an article explaining why in some case we need to override these methods and what exactly they are doing:
http://javarevisited.blogspot.ca/2011/02/how-to-write-equals-method-in-java.html
Normally you can auto-generate them withing your IDE, in NetBeans you can go to: Source - Insert Code - Equals and Hashcode.
Then it should work.
Related
I have a class of persons.
Public class Person{
private String name = "";
public Person(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
Now I have another class and inside the class I declared an arraylist
public class AddPerson {
public ArrayList<Person> pers = new ArrayList<Person>();
//here we add some persons to the arraylist
pers.add(new Person("Simon"));
pers.add(new Person("Oscar"));
pers.add(new Person("Alfred"));
String name = "Simon";
pers.contains(name); //return false
pers.equals(name); //return false
//I also want to be able to return the value and index of the name in arraylist if it exsists.
if(pers.contains(name)) //return index and value
}
When I try to check if two strings are equal or if a string is already in my list I get both false. I did some research and I saw that I need to override my equals method (and mabey hash and contains method as well). I do not know how to do it and I could not find a good reference how to do it. Please help me to achive that.
Here the problem is you are comparing a Person object with String object using the contains method.So actually in this case there is no point of implementing equals() method and hashCode() methods or using the contains() method to solve this .Only you have to do is check if person's attribute name is equal to your comparing String called name.
Sample solution:
String name="Simon";
Person result = null;//To store the person object if a person name Simon found in the list
int personIndex = -1; //To store the index of founded person
int indexCount =-1;//To maintain the current index value of arrayList
for(Person tempPerson:pers){//Iterating the list to find a person name Simon
indexCount++;
if(pers.getName().equals(name)){
personIndex = indexCount;
result = tempPerson;
}
}
Now you can use the values in personIndex and indexCount variables for future calculations.You can use a condition like if(personIndex >= 0) to check if really a person found with the comparing name after the iteration and then you can get the result variable value.
That is because you are trying to compare a string ("simon") and an object Person built from a string (Person("Simon")). These are two different objects, and it is thus normal to have false as a result.
Whether you want to compare two Person (this would make sense) or you are actually trying to compare a string and a person are it is most certainly a bad idea (you can't actually compare apples and oranges, well this is the same here).
What you might want to do is whether
to override Person's equals method to, for example, return true if they have the same name. => comparing Persons
to iterate on your pers array and fetch it's name property via getName() to compare it with you name string => comparing Strings
1 =>
#Override
public boolean equals(final Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
final Person person = (Person)o;
return name.equals(person.name);
}
#Override
public int hashCode() {
return Objects.hash(name);
}
2 =>
for (final Person person : pers) {
if(name.equals(person.getName())){
// ...
}
}
I have one ArrayList of 10 Objects.
List<Person> persons = new ArrayList<>();
persons.add(new Person("Jean", "Pol", "receptionist", 29));
persons.add(new Person("Jef", "Snijders", "guardener", 42));
persons.add(new Person("Piet", "Peters", "truck driver", 54));
persons.add(new Person("Peet", "Polders", "professor", 63));
persons.add(new Person("Nell", "Van Den Walle", "student", 19));
persons.add(new Person("Nady", "Van Toren", "cleaning", 27));
persons.add(new Person("Jenny", "De Koster", "police", 39));
persons.add(new Person("Malena", "Zetterman", "air traffic controler", 45));
persons.add(new Person("Medina", "Zegers", "test engineer", 25));
persons.add(new Person("Horaire", "Safrina", "manager", 39));
Another method in the applications creates an changed object:
Person changed = new Person("Jean", "Pol", "officer", 30);
How do I find this object in the list, and update the list?
(this should actually update the first object in the list)
This is the Person bean:
public class Person {
private String firstName;
private String lastName;
private String jobTitle;
private int age;
public Person() {
}
public Person(String firstName, String lastName, String jobTitle, int age) {
this.firstName = firstName;
this.lastName = lastName;
this.jobTitle = jobTitle;
this.age = age;
}
// Getters and setters
...
}
Changing an element in the List can be done by :
persons.set(0,changed);
However, finding the index of the element to change requires iterating over the entire List. You should consider using a HashMap instead (where the key identifies the Person).
Then
persons.put (personID, changed);
will replace the Person whose ID is personID (you'll need to have some unique property in the Person class, and override hashCode and equals in order to make that work).
You should tell java about "On what basis should i consider two person equals"? For that you have to override equals() method and do an equality check based on firstName and lastName. However since it is a list, so you will have to iterate over it and use contains(Person p) method to check if it exists (Which will use equals method). Once you find a matching Person object, you can replace it (using the index).
first decide which property or properties can be used to verify if 2 objects are equal then override equals and hashcode for persons and then iterate and compare then replace when found.
the best approach to find the object is to override two methods equals(Object o) and hashCode() within your Person class, this will define a unique Person
your Person class:
class Person {
...
#Override
public boolean equals(Object o){
// your code here
}
#Override
public int hashCode(){
//your code here
}
}
if ordering is not important to you , you can use HashMap
for example :
Person p;//
myMap.put(p.hashCode(),p);
then from other part of your application you get your person;
Person otherP;//
myMap.put(otherP.hashCode(), otherP) // this will replaces the previous person with the same hashCode with the modified code
if you don't want to add a person that is not already there, you can check if it exists first
if(myMap.containsKey(otherP.hashCode()){
myMap.put(otherP.hashCode(), otherP);//
}
generate hashcode and equals methods in your bean class for the variable you want to check for similarity (in your case the firstName property in person class).if using eclipse then pressing ctrl+shift+s shows you the option to generate hashcode and equals methods.
what this does is to override the default equals method. Please make sure that you are selecting only the properties which you know will be same.
if (List.contains(new_object)) { // checking if object is in the list
int indexPos = List.indexOf(new_object); // getting the index if there
dbStockObjList.set(indexPos, new_object);//adding it in the index
}
the hashcode and equals methods for your bean would look like this:
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((firstName == null) ? 0 : firstName.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;
return true;
}
hope this answers your question properly.
You can use the List#indexOf(obj) method to get the index of the "identical" object, and update it using List#set(index, object).
Note that it will require you to override equals() method for your object.
Also note: this operation is inefficient, and if the list is large and the number of changes is frequent - consider switching from a list to a "smarter" data type, such as a Set.
I have a collection of objects, A.
class A{
String name;
Collection<B> listOfB;
}
class B {
String address;
String phone;
int age;
}
I want to create new collection of A objects, where 2 objects have the same name, address, and phone. Can anyone tell me if this is the best way to do this?
I create a map of Key-A. The key would be as follows:
Key {
String name;
String address;
String phone;
}
I only as A objects to the list if their corresponding Key is not present.
If I understand your question correctly you want a map Map<Key, A>. The important thing is that you define equality and the hash code (in case you want a hash map) for the Key:
class Key {
String name;
String address;
String phone;
#Override // override in Object
public boolean equals(Object other) {
if(!other instanceof Key) return false;
Key otherKey = (Key) other;
return name.equals(otherKey.name) && address.equals(otherKey.address) && phone.equals(otherKey.phone); // check for null if fields can be null
}
#Override // override in Object
public int hashCode() {
return name.hashCode() ^ address.hashCode() ^ phone.hashCode(); // or something along those lines
}
}
Also good idea to create a constructor for the Key and make the fields private and final.
I'm not sure how this key is derived though. Ideally, the Key would somehow be derived from A, or - even better - A would have a hashCode and equals method so you do not need a map but you can use a Set. This really depends on the data you want to model though and your question is not clear enough to give a specific recommendation.
First, implement hascode and equals method in class B.
In equals method return true when name,phone and adress are the same.
Second time, create your map like this=
HashMap<B,A> myMap;
A key in a map is always unique.
In an ArrayList, I have the same kind of objects. Each object has an id, name, and number as their fields. There is a chance that more than one object will have the same phone number. How can I make the ArrayList in such a way that all the ArrayList objects have distinct phone numbers?
override in your class methods equals() and hashCode(). In equals you will compare by phone number. Generate hashcode from your phone number too.
Now you are ready to use Set interface which will compare your objects by phone numbers automatically and exclude duplicates.
example below:
public class Test {
private int id;
private String name;
private String phoneNumber;
public Test(int id, String name, String phoneNumber) {
this.id = id;
this.name = name;
this.phoneNumber = phoneNumber;
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Test test = (Test) o;
return phoneNumber.equals(test.phoneNumber);
}
#Override
public int hashCode() {
return phoneNumber.hashCode();
}
}
now instead of using List<Test> arr = ArrayList<Test>(), use Set<Test> mySet = new HashSet<Test>().
Try Set.
A collection that contains no duplicate elements.
First solution that comes to my mind is to use a HashMap.
Simply create a HashMap with the 'phonenumber' as key and your object as the value. After adding all the elements, you will have the list of objects with unique phone numbers. Simply iterate over this to create the List that you need.
I have a Java class as
class Students{
private String fName;
private String lName;
private String uName;
public Students(String fName, String lName, String uName) {
this.fName = fName;
this.lName = lName;
this.uName = uName;
}
public String getuName() {
return uName;
}
public void setuName(String uName) {
this.uName = uName;
}
public String getfName() {
return fName;
}
public void setfName(String fName) {
this.fName = fName;
}
public String getlName() {
return lName;
}
public void setlName(String lName) {
this.lName = lName;
}
}
Also I call this using
public class TestClass {
public static void main(String[] args) {
Students students1 = new Students("xyz","abc","xyzAbc");
Students students2 = new Students("poi","son","poison");
Students students3 = new Students("yog","jos","yogjos");
Students students4 = new Students("xyz","abc","xyzAbc");
Students students5 = new Students("pon","son","xyzAbc");
Students students6 = new Students("yog","jos","someotherUName");
Students students7 = new Students("yog","jos","someotherUName2");
List studentList1 = new ArrayList();
List studentList2 = new ArrayList();
studentList1.add(students1);
studentList1.add(students2);
studentList1.add(students3);
studentList2.add(students4);
studentList2.add(students5);
studentList2.add(students6);
}
}
Now I want a filtered list which would contain only unique "uName" values. Thus I want the comparison between "uName" field of each list and remove common ones.
At the end I would want 2 filtered list for studentList1 and studentList2.
I read about the removeAll method, but it seems to work with List of Integer/String data and not with List of Objects (as in my case).
You can put your list to set and then (if you need) to take it back:
new ArrayList(new HashSet<String>(list)) creates list that contains only unique elements from source list.
1. If you want each list to have unique uName value, then you can use TreeSet from java.util.Collection along with Interface Comparator from java.util.Comparator.
2. If you want to merge both the list and have unique uName, then combine both the list and then use TreeSet and Comparator.
3. Comparator gives the flexibility to compare in more than one way...
You can still use removeAll if the Objects in the List implement equals() properly.
AbstractCollection, which is the base for most kind of List implementations (including ArrayList) uses contains() in its implementation of removeAll. ArrayList's implementation of contains relies on indexOf(), which lastly uses equals().
You could implement equals() in your Student class to specify that an Student is equal to another if and only their uName fields are equal.
Please note that equals has associated semantics (see its javadoc), and you should be careful when choosing how to implement it. Consider if two student instances really represent the same student when their uNames are equal. In my opinion, this sounds like a very specific requirement of how to sort these things out and should not impact the semantics of the class.
You'll be much better off with #AlexR or #KumarVivekMitra's approach.
Firstly, you should be typing your lists:
List<Students> studentList1 = new ArrayList<Students>();
Secondly, implement hashCode() and equals() on your Students class that both delegate to uName:
public boolean equals(Object o) {
return o instanceof Students && ((Students)o).uName.equals(uName);
}
public int hashCode() {
return uName.hashCode();
}
Now removeAll() will work just fine.
Another option is to use Set, which only allows unique values as determined by the equals() method. If you add the above methods to your class, you could just do this:
Set<Students> students = new HashSet<Students>();
then add what you like to it and there will only ever be unique uName students in it.
btw, you should name your class in the singular - ie Student not Students.
You could also try using the apache commons CollectionUtils.disjunction. (link: http://commons.apache.org/collections/apidocs/org/apache/commons/collections/CollectionUtils.html#disjunction(java.util.Collection, java.util.Collection))
Your class Student should override methods hashcode and equals, so youy object can be unique by name. Here you can read how to do that.
Also note that all objects which are maintained in some collection should have those methods overriden, so you always know how are they compared.
In next step you can use removeAll method or the solution with Set, it's up to you :-)
Set example
List<String> list = new ArrayList(new HashSet<String>(studentList)); // here is your unique list
Or you could use custom Comparator instead of overriding hashcode and equals but if you want your students always unique, you should override them
A full working solution could be as follows.
Class Student{
.....
......
.....
public boolean equals(Object o) {
return o instanceof Students && ((Students)o).uName.equals(uName);
}
public int hashCode() {
return uName.hashCode();
}
}
Set studentList1 = new hashSet();
Set studentList2 = new hashSet();
Put your elements in these Sets.
Also if you want unique non-matching elements in both Sets. then write as follows.
studentList1.removeAll(studentList2 );