I have requirement to put "Name" and "phonenumber" in map.
I dont understand which thing I put as key and value in hashmap.
my requirement is we can and name with phone number and search with name.
like Name:"sanjay" phoneNumber:"111";
Name:"Krish" phoneNumber:"222";
later search it by name if I search 'sanjay' it provide me sanjay's phonenumber.
and, there is more then one user with same name and one user may have more then one phonenumber.
Thanks.
If you have a Person class, make a map like: Map<Person, Collection<String>>.
Then you can find phone numbers by doing map.get(somePerson), which returns null if the person doesn't exist.
You could also consider making a PhoneNumber class, which contains the string value of a validated phone number: Map<Person, Collection<PhoneNumber>>.
Use a class wrapper:
public class Person {
private List<String> phoneNumbers;
private String fullName;
//getters, setters, constructors for field values
#Override
public boolean equals(Object o) {
if (!(o instanceof Person) {
return false;
}
Person p = (Person) o;
return this.fullName.equals(p.fullName); //and other qualifying things
}
#Override
public int hashcode() {
//account for fields that you use in #equals(Object)
}
}
Then you can index based on whatever you want:
/* Full name => People */
Map<String, List<Person>> people = new HashMap<>();
/* Number => Person */
Map<String, Person> people = new HashMap<>();
Keep in mind, if you only compare the name in equals(Object), you're back to square one. Add more things to compare to be consistent with the uniqueness.
Hash maps great power is the ability to find the values in O(1) efficiency.
For this to work, the key must be the object you search by.
For example, if you want to search by name than your key should be the name.
And since a person can have several phone numbers, the value should be a List of phone numbers.
if you want to find the person name according to the phone number you should handle this the other way around - the key would be the phone number and the value would be the person name.
Perhaps you want both...
There are good answers above, may be this will also helps
Here Student made as key by overriding hashCode() and equals() method.
public class Student {
public String studentId;
public String studentName;
public Student(String studentId, String studentName) {
this.studentId=studentId;
this.studentName =studentName;
}
#Override
public int hashCode() {
return 1234;
}
#Override
public boolean equals(Object o) {
if (o instanceof Student) {
Student student=(Student)o;
if (this.studentId.equalsIgnoreCase(student.studentId)) {
return true;
} else {
return false;
}
} else {
return false;
}
}
}
Phone Number class :
public class PhoneNumber {
public String phoneNumber;
public PhoneNumber(String phoneNumber) {
this.phoneNumber =phoneNumber;
}
}
Person Class :
import java.util.HashMap;
import java.util.Set;
import java.util.List;
import com.google.common.collect.Lists;
public class Person {
public static void main(String[] args) {
Student e1=new Student("e001","studentOne");
Student e2=new Student("e002","studentTwo");
PhoneNumber d1 = new PhoneNumber("9999999998");
PhoneNumber d2 = new PhoneNumber("9999999999");
List listOfPhoneNumbersOfStudentOne = Lists.newArrayList(d1,d2);
PhoneNumber d3 = new PhoneNumber("9999999997");
PhoneNumber d4 = new PhoneNumber("9999999996");
List listOfPhoneNumbersOfStudentTwo = Lists.newArrayList(d3,d4);
/* Here Student made as key by overriding hashCode() and equals() method.*/
HashMap<Student, List<PhoneNumber>> map=new HashMap<Student, List<PhoneNumber>>();
map.put(e1, listOfPhoneNumbersOfStudentOne);
map.put(e2, listOfPhoneNumbersOfStudentTwo);
Set<Student> key=map.keySet();
for (Student student : key) {
System.out.println(student.studentId+" "+student.studentName +" ");
}
}
}
public class Assignment4 {
HashMap map = new HashMap<>();
public void addContact(String name, Integer number) {
map.put(name, number);
}
public void getphoneNumber(String name) {
if (map.containsKey(name)) {
Integer a = map.get(name);
System.out.println("Contact of " +name+" is " + a);
}
}
public static void main(String[] args) {
Assignment4 a4 = new Assignment4();
a4.addContact("vishal", 10345);
a4.addContact("sachin", 30456);
a4.addContact("sai", 30458);
Scanner s=new Scanner(System.in);
System.out.println("Enter name to get contact details");
a4.getphoneNumber(s.next());
s.close();
}
}
Related
This is the code I wrote so far for the other things I need to do. The main problem is that even with so much info I can't understand how to do it.
Create a map from the farm list which has like key the salary and like value the list of employee that has that salary. Display the map content, and for each employee display the farm in which is working
public class Employee implements Comparable<Employee> {
private String name;
private Integer salary;
public Employee (String name , Integer salary) {
this.name = name;
this.salary = salary;
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setSalary(Integer salary) {
this.salary = salary;
}
public Integer getSalary() {
return salary;
}
public String toString() {
return name + " " + salary;
}
public int compareTo(Employee emp) {
return this.salary.compareTo(emp.getSalary());
}
}
Farm class
public class Farm {
private String name;
private Integer surface;
List<Employee> emp = new ArrayList<Employee>();
public Farm(String name , Integer surface) {
this.name = name;
this.surface = surface;
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setSurface(Integer surface) {
this.surface = surface;
}
public int getSurface () {
return surface;
}
public String toString() {
return name + " " + surface;
}
public void makeList(String ename , Integer esalary) {
this.emp.add(new Employee(ename,esalary));
}
public void getList() {
for(Employee el : emp)
System.out.println(el);
}
public Employee getMostPaidEmployee() {
return Collections.max(emp);
}
}
And my main one
public static void main(String args[])
{
List <Farm> FarmList = new ArrayList<Farm>();
Farm farm1 = new Farm("Tiguana" , 700);
farm1.makeList("Mihai", 30000);
farm1.makeList("Vladimir", 4000);
farm1.makeList("Tusnic", 3000);
farm1.getList();
System.out.println(farm1.getMostPaidEmployee());
Farm farm2 = new Farm("Tipirei" , 800);
farm2.makeList("Mihai", 30000);
farm2.makeList("Mihail", 40000);
farm2.makeList("Armando", 50000);
farm2.makeList("ASihai", 60000);
System.out.println(farm2.getMostPaidEmployee());
FarmList.add(farm2);
FarmList.add(farm1);
}
Map< Integer , List< Employee > >
Sounds like you want to build a Map< Integer , List< Employee > >. The key, of type Integer (object, not primitive int), is the salary. The value is a List of employees with that particular salary.
So you need to instantiate such a Map, probably a HashMap, or perhaps a SortedMap such as TreeMap. Then as you loop the employees, you see if their salary has already been added as a key to the map. If not, add the salary as a key, and create an empty List object as the value. Add that particular employee to the new list. If the salary is already present, retrieve the list, add the employee.
To report by farm, you need to find which farm hired that employee. You will loop the keys of the map, for each key retrieve its list of employees, and then loop those employees. For each employee, loop all the farms, and retrieve each farm’s list of employees, and see if the target employee is in that list. If so, you know the farm of the employee in the list on the map.
One flaw in your code is defining a compareTo on Employee by salary. Intuitively we can tell that does not smell right. You should instead have an identifier on each employee, like most any company assigns an “employee id” to each person hired. For the sake of your exercise, I would just use a UUID as the id. Add a member field of type UUID to your Employee class. Define compareTo using that object.
As this is obviously homework, I think I have said enough. You should be able to figure this out following my prose. You can also search Stack Overflow for many many examples of maps with a list as the value, and other such issues.
In real work, we would likely be concerned with concurrency issues. But I assume that was not intended as part of your school assignment.
See also the coding-style tips I posted as Comments on the Question.
This is how you gonna do it :
Map<Integer, List<Employee>> map = new HashMap<>();
for(Farm f : FarmList){
for(Employee e : f.emp){
if(!map.containsKey(e.salary)){
map.put(e.salary, new ArrayList<>());
}
map.get(e.salary).add(e);
}
}
Be sure to add the field of FarmName to your employee and override toString() method in Employee class so you can display what's asked.
I have Overridden equals method of Person class comparing the name attribute of class and if they are equal returning back true from equals method.
When i am creating the instance of Person object and using it as key in hashmap, while retrieving using a new object with same name i am not able to retrieve back the associated value from hashMap.
Below is my
import java.util.HashMap;
import java.util.Map;
public class ToStringTest {
public static void main(String[] args) {
Person person = new Person("Jack", "California");
Map<Person,String> personsMap = new HashMap<>();
personsMap.put(person,"MyCar");
Person otherPerson = new Person("Jack", "California");
System.out.println(personsMap.get(otherPerson));
}
}
class Person {
String name;
String city;
public Person(String name, String city) {
this.name = name;
this.city = city;
}
#Override
public String toString() {
return "Name : " + this.name + ", City : " + this.city;
}
#Override
public boolean equals(Object o) {
Person person = (Person) o;
if(person.name.equals(this.name)){
return true;
}
return false;
}
}
This is printing null while retrieving from using otherPerson object.
Could someone please explain this behavior.
When you add new person in map personsMap.put(person,"MyCar"); first of all if key is not null the position where the element will be put is determined. It is determined by calling hashcode method for key. There are a few steps after but it doesn't matter for this example.
Since you don't override hashcode() your person and otherPerson will have different hashcode.
The same happens when you try to get value by some key. To find position where the element is, hashcode() will be invoked. But otherPerson has different hashcode and it will lead to position where is no item (null)
equals() is used when at the same position there are many elements (in list or tree structure). Then to find the right item they will be compared by equals() method
I have Employee class and want to use this class as a key in HashMap and value of that map will be a string. To achieve this, however, I have overridden the equals and hashcode methods in Employee class itself. I have another class to test that whether Employee class key will work correctly or not. After testing, I found that map is storing duplicate keys. Please find below source code and output:
Employee.java
public class Employee {
private int empId;
private String empName;
private int empAge;
Employee(){}
public int getEmpId() {
return empId;
}
public void setEmpId(int empId) {
this.empId = empId;
}
public String getEmpName() {
return empName;
}
public void setEmpName(String empName) {
this.empName = empName;
}
public int getEmpAge() {
return empAge;
}
public void setEmpAge(int empAge) {
this.empAge = empAge;
}
#Override
public boolean equals(Object obj) {
if(obj == null) return false;
if(!(obj instanceof Employee)) return false;
Employee e = (Employee)obj;
return e.empId == this.empId;
}
#Override
public int hashCode() {
return this.empId;
}
#Override
public String toString() {
// TODO Auto-generated method stub
return "Id : "+empId+" Name : "+empName+" Age : "+empAge;
}
}
TestEmployee.java
import java.util.HashMap;
import java.util.Map;
public class TestEmployee {
/**
* #param args
*/
public static void main(String[] args) {
Map<Employee, String> empMap = new HashMap<Employee, String>();
Employee emp1 = new Employee();
emp1.setEmpId(10);
emp1.setEmpName("A");
emp1.setEmpAge(20);
Employee emp2 = new Employee();
emp2.setEmpId(20);
emp2.setEmpName("B");
emp2.setEmpAge(21);
empMap.put(emp1, "1");
empMap.put(emp2, "2");
System.out.println(empMap);
emp1.setEmpId(20);
System.out.println(" emp1.equals(emp2) : "+emp1.equals(emp2));
System.out.println(" emp1.hashCode() : "+emp1.hashCode()+" emp2.hashCode() : "+emp2.hashCode());
System.out.println(empMap);
}
}
Output:
{Id : 20 Name : B Age : 21=2, Id : 10 Name : A Age : 20=1}
emp1.equals(emp2) : true
emp1.hashCode() : 20 emp2.hashCode() : 20
{Id : 20 Name : B Age : 21=2, Id : 20 Name : A Age : 20=1}
Please let me know how can I use unique Employee in map key - uniqueness will decide based on employee ID.
Do not update the value that is used for hashcode while the object is in a hashmap. The hashcode will be used to decide where to put the object. If you update it afterwards, this update is not "picked up" by the hashmap so at best you have duplicates, at worst you can't retrieve the value connected to the updated key anymore.
UPDATE
Please check the javadoc for more information but high level the HashMap chooses a bucket to put the value in based on the hashcode of the key. If you try to retrieve the value with the key, it will look at the hashcode of the key, determine which bucket it should be in, then check that bucket and retrieve the value.
However if between the put() and the get() the hashcode of the key changes, the hashmap might put it in bucket "A" and try to get it in bucket "B".
In your equals method instead of using '==' reference comparison use equals method
as '==' comparison checks for reference equality instead of value comparison.
Like
return e.empId.equals(this.empId);
Java Integer class properly overrides equals and it will give you correct result.
I want the user to enter the name of the object to be used in the code. For example, if I have a class
public class Person{
.......
}
now instead of me creating an object with a specific name like
Person student;
I want the user to enter the name for the object maybe like teacher, and then an object teacher of the class person will be created.
I do not know if this is even possible in java, many of the solutions I looked up were using a map, but the explanations were not clear enough for me as I am new to java.
So, if anyone could explain how it can be done with code snippets it would be wonderful.
Also please explain how hashmaps work in java and if they can be used to implement the problem above. I would be really grateful if explained with code examples
It's not possible. Names of local variables are not even persistent in the compiled Class file. Names of fields are there, as it is the part of API, but you would have to modify the Class file runtime - and that is not what do you want.
With Hashtable, it may be done like this:
Hashtable<String, Person> hashtable = new Hashtable<>();
hashtable.put("student", new Person());
Then you may get your "variable" by:
Person person = hashtable.get("student");
When I guess what you are trying to do, this is some more helpful example:
import java.util.Hashtable;
import java.util.Scanner;
public class Test {
public static class Person {
public final String name;
public final int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
#Override
public String toString() {
return "Name: " + name + ", age: " + age;
}
}
public static class PersonsList {
private Hashtable<String, Person> persons = new Hashtable<String, Test.Person>();
public void addPerson(Person person) {
this.persons.put(person.name, person);
}
public Person findPerson(String name) {
return persons.get(name);
}
#Override
public String toString() {
return persons.toString();
}
}
public static void main(String[] args) {
PersonsList personsList = new PersonsList();
Scanner scanner = new Scanner(System.in);
while (scanner.hasNextLine()) {
String line = scanner.nextLine();
if (line.equals("END")) {
break;
}
try {
String[] parts = line.split(" ");
String name = parts[0];
int age = Integer.valueOf(parts[1]);
personsList.addPerson(new Person(name, age));
} catch (NumberFormatException e) {
System.out.println("Age must be an decimal non-floating-point number.");
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println("You must enter both name and age");
}
}
scanner.close();
System.out.println(personsList);
}
}
I'm looking for a Collection type data structure to implement the following. Say I have a class like this:
class Person() {
String homeTown; // key
String sex; // key
String eyeColour; // key
String name;
long height;
// other stuff....
}
I am processing multiple Person objects. I want to organise them into sets whereby each set contains Person objects with the same homeTown, sex and eyeColour. At the moment I am implementing something like this:
Map<String, HashSet<Person>> = new HashMap<String, HashSet<Person>>;
where the key is a concatanation of the homeTown, sex and eyeColour. This works but seems a bit untidy - can anyone suggest a more elegant solution or a better data structure to use, thanks?
You could restructure your class to make the key explicit. This is more robust than simply concatenating the key values and avoids any additional object creation overhead at the point when you wish to store your Person instance in a Map, because you've eagerly created the key in advance.
public class Person {
public class Key {
private final String homeTown;
private final String sex;
private final String eyeColour;
public Key(String homeTown, String sex, String eyeColour) { ... }
public boolean equals(Object o) { /* Override to perform deep equals. */ }
public int hashCode() { /* Could pre-compute in advance if the key elements never change. */ }
}
private final Key key;
private final String name;
private final long height;
public Person(String homeTown, String sex, String eyeColour, String name, long height) {
this.key = new Key(homeTown, sex, eyeColour);
this.name = name;
this.height = height;
}
public Key getKey() {
return key;
}
public String getName() { return name; }
public long getHeight() { return height; }
}
Create an object to model your key. For example class PersonKey { String homeTown, sex, eyeColour } (getters and setters omitted for brevity)
Implement the equals and hashCode method for this object.
Use this object as the key in your Map.
Either remove the attributes from your Person object or replace them with a reference to your PersonKey object.
In addition, consider making the type of your map the following i.e. you don't need to specify what type of Set you are using as the key to your map.
Map<String, Set<Person>> = new HashMap<String, Set<Person>>();
And, if you are using a Set<Person> then you'll need to override equals and hashCode for the Person as well, otherwise the Set cannot correctly determine if two Person objects represent the same person or not, which is needed to make sure the collection contains only unique elements.
org.apache.commons.collections.map.MultiValueMap
You can use guava's Sets.filter method to filter the person objects.
Example:
Person class:
public class Person {
String name;
String hometown;
int age;
public Person(String name, String hometown, int age) {
this.name = name;
this.age = age;
this.hometown = hometown;
}
#Override
public int hashCode() {
int hash = 17;
hash = 37 * hash + name.hashCode();
hash = 37 * hash + hometown.hashCode();
hash = 37 * hash + age;
return hash;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
Person p;
if (obj instanceof Person)
p = (Person) obj;
else
return false;
if (this.name.equals(p.name) && this.hometown.equals(p.hometown)
&& this.age == p.age)
return true;
return false;
}
#Override
public String toString() {
StringBuilder b = new StringBuilder();
b.append("[name = ").append(name).append("\n");
b.append("home town = ").append(hometown).append("\n");
b.append("age = ").append(age).append("]");
return b.toString();
}
}
TestGuavaFilter class:
public class TestGuavaFilter {
public static void main(String[] args) {
Set<Person> set = new HashSet<Person>();
set.add(new Person("emil", "NY", 24));
set.add(new Person("Sam", "NY", 50));
set.add(new Person("george", "LA", 90));
System.out.println(Sets.filter(set, new FilterHomeTown("NY")));
}
}
class FilterHomeTown implements Predicate<Person> {
String home;
public FilterHomeTown(String home) {
this.home = home;
}
#Override
public boolean apply(Person arg0) {
if (arg0.hometown.equals(this.home))
return true;
return false;
}
}
The advantage of using a filter is that you can filter Person object in any way ,suppose you want to filter only using home-town and not the other 2 attributes this will helpful.More over since guava's filter only produces a view of the the real Set,you can save memory.