I have 2 ArrayList. And I want elements with common phone.
ArrayList<Contact> phone_contacts;
ArrayList<Contact> registered_users;
I used below method to get common elements:
ArrayList<Contact> common_contacts = new ArrayList<Contact>(phone_contacts);
common_contacts.retainAll(registered_users);
But, the result I get is empty. How can I get common phone contact in common_contacts ArrayList?
Contact
public class Contact {
private String name;
private String phone;
public Contact(String name, String phone) {
this.name = name;
this.phone = phone;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
}
First, if you are treating a phone number as an identifier, I would advise caution. Falsehoods Programmers Believe About Phone Numbers
With that said...
retainAll ultimately uses the equals method. Given that you have a custom object (and not something like a String or int that have a defined equals), the simplest method would be to define an equals method for Contact that returns true if the two have the same phone number.
However, that might not be what you are looking for. For example, equals might need to check the name in other contexts.
There are a couple other approaches you could take. Since you mentioned Android, Java 8 streams are currently out. An Iterator loop might do the job. Collect all of the phone numbers for registered users into a Set (so you have the unique list), then start with a List of all of your contacts, and remove any that don't have a phone number from that set.
Set<String> registeredPhoneNumbers = new HashSet<>();
for (Contact c : registered_users) {
registeredPhoneNumbers.add(c.getPhone());
}
List<Contact> common_contacts = new ArrayList<>(phone_contacts);
for (Iterator<Contact> iter = common_contacts.iterator(); iter.hasNext();) {
Contact c = iter.next();
if (!registeredPhoneNumbers.contains(c.getPhone())) {
iter.remove();
}
}
Since you mentioned in comments that there could be a million distinct registered_users, this might be more space-efficient:
Set<String> phoneNumbers = new HashSet<>();
for (Contact c : phone_contacts) {
phoneNumbers.add(c.getPhone());
}
Set<String> overlappingNumbers = new HashSet<>();
for (Contact registered : registered_users) {
if (phoneNumbers.contains(registered.getPhone())) {
overlappingNumbers.add(registered.getPhone());
}
}
List<Contact> common_contacts = new ArrayList<>();
for (Contact contact : phone_contacts) {
if (overlappingNumbers.contains(contact.getPhone())) {
common_contacts.add(contact);
}
}
}
You may want to check the phone number for null as well.
Add these lines to your Contact class:
#Override
public boolean equals(Object obj) {
return obj instanceof Contact &&
this.name != null && this.name.equals(((Contact)obj).name) &&
this.phone!= null && this.phone.equals(((Contact)obj).phone);
}
Ref: https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html#equals-java.lang.Object-
See Also: hashCode()
If you use the method RetainAll in the List the you will get the common objects between 2 Lists..\
Example:
consider the lists of integers, (just for the sake of the example) it will work with your class...
public static void main(String[] args) {
List<Integer> list1 = new ArrayList<Integer>(Arrays.asList(0, 1, 2, 3, 4, 5));
List<Integer> list2 = new ArrayList<Integer>(Arrays.asList(1, 3, 5));
List<Integer> list3 = new ArrayList<Integer>(list1);
list3.retainAll(list2);
System.out.println("List1:" + list1);
System.out.println("List2:" + list2);
System.out.println("List common:" + list3);
}
In your case the class contacts needs to be modified so the Method ArrayLst.retainAll() can somehow identify whether a Contact is the same as the other using as criteria the Phone number...
Modify/Improve the Contact Class by adding the HashCode and Equals:
but you need to use as criteria only the phone Number
public class Contact {
private String name;
private int phone;
public Contact(String name, int phone) {
this.name = name;
this.phone = phone;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
#Override
public String toString() {
return "Contact [name=" + name + ", phone=" + phone + "]";
}
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + phone;
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Contact other = (Contact) obj;
if (phone != other.phone)
return false;
return true;
}
public int getPhone() {
return phone;
}
public void setPhone(int phone) {
this.phone = phone;
}
}
Implement the List of Contacts and call the method RetainAll
public static void main(String[] args) {
List<Contact> list1 = new ArrayList<Contact>(Arrays.asList(new Contact(UUID.randomUUID().toString(), 1),
new Contact(UUID.randomUUID().toString(), 2), new Contact(UUID.randomUUID().toString(), 3),
new Contact(UUID.randomUUID().toString(), 4), new Contact(UUID.randomUUID().toString(), 5)));
List<Contact> list2 = new ArrayList<Contact>(Arrays.asList(new Contact(UUID.randomUUID().toString(), 1),
new Contact(UUID.randomUUID().toString(), 3), new Contact(UUID.randomUUID().toString(), 5)));
List<Contact> list3 = new ArrayList<Contact>(list1);
list3.retainAll(list2);
System.out.println("List1:" + list1);
System.out.println("List2:" + list2);
System.out.println("List common:" + list3);
}
Related
I'm working on a school project and I have the JUnit test almost here but I cannot for the life of me get this to work.
Contact looks like:
public class Contact {
private String contactID;
private String firstName;
private String lastName;
private String phoneNumber;
private String address;
public Contact (String contactID, String firstName, String lastName, String phoneNumber, String address)
{
//ContactTests Tests
//test to see if contact ID is NOT null or above 10 characters
if (contactID == null || contactID.length()>10)
{
throw new IllegalArgumentException("Invalid contact ID");
//not updating because says do not update it
}
//test to see if first name is NOT null or above 10 characters
if (firstName == null || firstName.length()>10)
{
throw new IllegalArgumentException("Invalid first name");
}
if (lastName == null || lastName.length()>10)
{
throw new IllegalArgumentException("Invalid last name");
}
//test to see if phone number is NOT null or not 10 characters
if (phoneNumber == null || phoneNumber.length()>10 || phoneNumber.length()<10)
{
throw new IllegalArgumentException("Invalid phone number");
}
//test to see if address is NOT null or more than 30 characters
if (address == null || address.length()>30)
{
throw new IllegalArgumentException("Invalid address");
}
//apply them
this.contactID = contactID;
this.firstName = firstName;
this.lastName = lastName;
this.phoneNumber = phoneNumber;
this.address = address;
}
//return the variables
//used within tests
public String getContactID() {
return contactID;
}
public String getFirstName() {
return firstName;
}
public String getLastName() {
return lastName;
}
public String getPhoneNumber() {
return phoneNumber;
}
public String getAddress() {
return address;
}
//for contactService need to create values here to get variables to set into the array
//used for First Name, Last Name, Phone Number, Address
//used within ContactServices
public void setFirstName (String firstName)
{
this.firstName = firstName;
}
public void setLastName (String lastName)
{
this.lastName = lastName;
}
public void setPhoneNumber (String phoneNumber)
{
this.phoneNumber = phoneNumber;
}
public void setAddress (String address)
{
this.address = address;
}
//test if two contacts are the same
//used in contactService and contactServiceTest
//geeksforgeeks.org/overriding-equals-method-in-java/ helped me in this idea of changing equals
//to becoming more complex
/*#Override
public boolean equals(Object test)
{
if (this == test)
{
return true;
}
if ((getClass() != test.getClass()) || (test == null))
{
return false;
}
Contact another = (Contact) test;
if (contactID == null)
{
if (another.contactID != null || (!contactID.equals(another.contactID)))
{
return false;
}
}
if (firstName == null)
{
if (another.firstName != null || (!firstName.equals(another.firstName)))
{
return false;
}
}
if (lastName == null)
{
if (another.lastName != null || (!lastName.equals(another.lastName)))
{
return false;
}
}
if (phoneNumber == null)
{
if (another.phoneNumber != null || (!phoneNumber.equals(another.phoneNumber)))
{
return false;
}
}
if (address == null)
{
if (another.address != null || (!address.equals(another.address)))
{
return false;
}
}
return true;
}*/
}
ContactService and ContactServiceTest look like;
import java.util.ArrayList;
import contact.Contact;
public class ContactService {
//will contain our list of contacts
//list was removed as working solely with array list now
private ArrayList<Contact> contacts;
public ContactService()
{
//beginning call for the array list
contacts = new ArrayList<>();
}
//need to have an add contact, remove contact and update contact feature
//set add contact to have all values
public boolean addContact(Contact contact)
{
boolean contactAlready = false;
//run through all the contacts in the list made
for (Contact contactList:contacts)
{
//test to see if already a contact
//if so make contactAlready true
if (contactList.equals(contact))
{
contactAlready = true;
}
}
//if not a contact add it as one
if (!contactAlready)
{
contacts.add(contact);
//after adding is now true
return true;
}
else
{
//ending false statement
return false;
}
}
//delete needed via contactID
public boolean deleteContact(String contactID)
{
//run through list of contacts
for (Contact contactList:contacts)
{
//if equals to contactID will remove and return
if (contactList.getContactID().equals(contactID))
{
//remove and return true
contacts.remove(contactList);
return true;
}
}
//else fail and return false
return false;
}
//update is trickiest due to needing to make sure still fits parameters
//"" means no change
public boolean updateContact(String contactID, String firstName, String lastName, String phoneNumber, String address)
{
//run through loop again
for (Contact contactList:contacts)
{
//if contactID matches, run through each with making sure not "" and meets requirements
//then return true as it did equal update.
if (contactList.getContactID().equals(contactID))
{
//set each of the values as long as meet's requirements nor empty
if(!firstName.equals("") && !(firstName.length()>10))
{
contactList.setFirstName(firstName);
}
if(!lastName.equals("") && !(lastName.length()>10))
{
contactList.setFirstName(lastName);
}
if(!phoneNumber.equals("") && (phoneNumber.length()==10))
{
contactList.setFirstName(phoneNumber);
}
if(!address.equals("") && !(address.length()>30))
{
contactList.setFirstName(address);
}
//return true as did update
return true;
}
}
//else fail and return false
return false;
}
}
ContactServiceTest
import static org.junit.jupiter.api.Assertions.*;
import org.junit.jupiter.api.Test;
import static org.junit.Assert.*;
import contact.Contact;
import contact.ContactService;
class ContactServiceTest {
//need to test add, delete and update
//templates
/*
* Contact("1413252", "Jane", "Doe", "4444444444", "Sample 24 Drive");
Contact("1309403", "Malleus", "Draconia", "2187123404", "Valley of Thorns");
Contact("9752319", "Vil", "Schoenheit", "9215501793", "Land of Proxynee");
*/
#Test
public void testAdd()
{
ContactService cs = new ContactService();
Contact contact = new Contact("1413252", "Jane", "Doe", "4444444444", "Sample 24 Drive");
assertTrue(cs.addContact(contact));
//assertEquals(true, cs.addContact(contact));
}
}
I would appreciate any help on this as I'm completely lost and I've gotten no help, sorry for the code dump I just wanted you to have a full picture of what's going on if something -or everything- is wrong.
The "ambigous" error is because the compiler cannot determine whether you are trying to invoke the assertTrue method of class org.junit.Assert or the assertTrue method of org.junit.jupiter.api.Assertions.
To fix this, just remove the following statement:
import static org.junit.Assert.*;
Moreover, here are some tips to improve your code:
Remove the comment of the equals method in Contact class, that method is fine. In addition, you can make Contact class implement the interface java.lang.Comparable and implement the method public int compareTo(Object o), which will be based on what you did for equals, but invoking compareTo instead of equals for each instance member of Contact.
If you follow the fist point, in your ContactService you don't need to visit your ArrayList of contact to verify the existance of an element, that is not necessary.
If you don't want to have duplicated elements in your list, Java gives you the possibility to choose another collection, which is made for the purpose (i.e. TreeSet).
Here is a revisited version of your ContactService:
package contact;
import java.util.ArrayList;
public class ContactService {
//will contain our list of contacts
//list was removed as working solely with array list now
private List<Contact> contacts;
public ContactService()
{
//beginning call for the array list
contacts = new ArrayList<>();
}
//need to have an add contact, remove contact and update contact feature
//set add contact to have all values
public boolean addContact(Contact contact)
{
if(!contacts.contains(contact)) {
return contacts.add(contact);
}
return false;
}
//delete needed via contactID
public boolean deleteContact(String contactID)
{
//run through list of contacts
for (Contact contactElement : contacts)
{
//if equals to contactID will remove and return
if (contactElement.getContactID().equals(contactID))
{
return contacts.remove(contactElement);
}
}
//else fail and return false
return false;
}
//update is trickiest due to needing to make sure still fits parameters
//"" means no change
public boolean updateContact(String contactID, String firstName, String lastName, String phoneNumber, String address)
{
//run through loop again
for (Contact contactList:contacts)
{
//if contactID matches, run through each with making sure not "" and meets requirements
//then return true as it did equal update.
if (contactList.getContactID().equals(contactID))
{
//set each of the values as long as meet's requirements nor empty
if(!firstName.equals("") && !(firstName.length()>10))
{
contactList.setFirstName(firstName);
}
if(!lastName.equals("") && !(lastName.length()>10))
{
contactList.setFirstName(lastName);
}
if(!phoneNumber.equals("") && (phoneNumber.length()==10))
{
contactList.setFirstName(phoneNumber);
}
if(!address.equals("") && !(address.length()>30))
{
contactList.setFirstName(address);
}
//return true as did update
return true;
}
}
//else fail and return false
return false;
}
}
In addition, here is another version of ContactServiceTest, where I just added a couple of more scenarios. Starting from this, you can go on and implement more tests, for example related to updateContact.
import static org.junit.jupiter.api.Assertions.*;
import static org.junit.jupiter.api.Assertions.assertTrue;
import org.junit.jupiter.api.Test;
import contact.Contact;
import contact.ContactService;
class ContactServiceTest {
//need to test add, delete and update
//templates
/*
* Contact("1413252", "Jane", "Doe", "4444444444", "Sample 24 Drive");
Contact("1309403", "Malleus", "Draconia", "2187123404", "Valley of Thorns");
Contact("9752319", "Vil", "Schoenheit", "9215501793", "Land of Proxynee");
*/
#Test
public void testAdd()
{
ContactService cs = new ContactService();
Contact contact = new Contact("1413252", "Jane", "Doe", "4444444444", "Sample 24 Drive");
assertTrue(cs.addContact(contact));
contact = new Contact("1413252", "Jane", "Doe", "4444444444", "Sample 24 Drive");
//assertEquals(true, cs.addContact(contact));
assertFalse(cs.addContact(contact));
}
#Test
public void testRemove()
{
ContactService cs = new ContactService();
Contact contact = new Contact("1413252", "Jane", "Doe", "4444444444", "Sample 24 Drive");
cs.addContact(contact);
assertTrue(cs.deleteContact("1413252"));
//assertEquals(true, cs.addContact(contact));
}
}
I have two different arrays oldUsers and newUsers containing instances of the class User. User contain firstname, lastname and age attributes. I want to know the number of oldUsers objects in the newUsers array that have the same attributes. Shall I use two for loops and compare the arrays one per one or is there a function that can do the same work ?
You first need to override equals() and hashCode(). Then you can implement an intersection() method.
Number of identical values: 2
------------------------------
- { 'firstname': 'Bob', 'lastname': 'Smith', 'age': 30 }
- { 'firstname': 'Robert', 'lastname': 'Brown', 'age': 51 }
Main
import java.util.*;
public class Main {
public static void main(String[] args) {
List<User> oldUsers = new ArrayList<User>();
List<User> newUsers = new ArrayList<User>();
List<User> intersect;
oldUsers.addAll(Arrays.asList(
new User("Bob", "Smith", 30),
new User("Tom", "Jones", 42),
new User("Robert", "Brown", 51),
new User("James", "Jones", 28)
));
newUsers.addAll(Arrays.asList(
new User("Robert", "Brown", 51), // Same
new User("Bob", "Smith", 30), // Same
new User("Tom", "Jones", 21),
new User("James", "Hendrix", 28)
));
intersect = intersection(oldUsers, newUsers);
System.out.printf("Number of identical values: %d%n%s%n",
intersect.size(), "------------------------------");
for (User user : intersect) {
System.out.printf("- %s%n", user);
}
}
// http://stackoverflow.com/a/5283123/1762224
public static <T> List<T> intersection(List<T> list1, List<T> list2) {
List<T> list = new ArrayList<T>();
for (T t : list1) {
if (list2.contains(t)) {
list.add(t);
}
}
return list;
}
}
User
public class User {
private String firstname;
private String lastname;
private int age;
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; }
public int getAge() { return age; }
public void setAge(int age) { this.age = age; }
public User(String firstname, String lastname, int age) {
super();
this.firstname = firstname;
this.lastname = lastname;
this.age = age;
}
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + age;
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;
User other = (User) obj;
if (age != other.age) return false;
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;
}
#Override
public String toString() {
return String.format("{ 'firstname': '%s', 'lastname': '%s', 'age': %d }",
firstname, lastname, age);
}
}
Alternative Methods
Set :: Retain All
public static <T> List<T> intersection(List<T> list1, List<T> list2) {
Set<T> set = new HashSet<T>(list1);
set.retainAll(new HashSet<T>(list2));
return new ArrayList<T>(set);
}
List :: Java 8 Filter Stream
public static <T> List<T> intersection(Collection<T> list1, Collection<T> list2) {
return list1.stream().filter(item -> list2.contains(item)).collect(Collectors.toList());
}
Assuming your User objects correctly implement equals() and hashCode(), I would use one of the lists' retainAll(Collection other) method to craft the intersection of both lists and then return its size.
If you have equals() and hashCode() implemented correctly, you can place all inputs from oldUsers array to Set and then check data from newUsers if they are in that Set or not. This will work in O(max(n, m)) (place data in Set is O(n), check newUsers if they are in Set is O(m), so you have O(n) + O(m) = O(max(n,m)), where n is size of oldUsers list and m is size of newUsers list).
For example:
private int numberOfSameUsers(ArrayList<User> oldUsers, ArrayList<User> newUsers) {
Set<User> oldUsersSet = new HashSet<>(oldUsers);
int counter = 0;
for (int i = 0; i < newUsers.size(); i++) if (oldUsersSet.contains(newUsers.get(i))) counter++;
return counter;
}
I'm new to Java and i've been bashing my head over the wall to solve this problem. Anyway below is a class that creates a Person and below that, is a class that creates a Phonebook using an ArrayList of type Person. I want to write the remove function (in order to remove a Person from the list) but my problem is that since i only get the name of the person i can't use the Indexof function (cause it requires object) to get at what position lies the name.
This is my first time using an ArrayList to store an Object so i'm not even sure
how my results would appear. I'm guessing that if the position of the name (in my list) is 10 then 11 would be the phone and 12 would be the address. Am i correct?
public class Person
{
private String name;
private String phone;
private String address;
public Person (String n, String p, String a)
{
this.name = n;
this.phone = p;
this.address = a;
}
public void setPhone(String newPhone)
{
this.phone = newPhone;
}
public String getName()
{
return this.name;
}
public String getPhone()
{
return this.phone;
}
public String getAddress()
{
return this.address;
}
public String print()
{
return "Name is : " + this.name + "\nPhone is : " + this.phone + "\nAddress is : " + this.address;
}
}
import java.util.*;
public class phoneBook
{
Scanner in = new Scanner ( System.in );
private ArrayList <Person> persons = new ArrayList <Person>();
private int i;
private boolean flag;
public void addPerson(Person p)
{
persons.add(p);
}
public void listPersons ()
{
System.out.println(persons);
}
public void lookUp (String theName)
{
flag = persons.contains(theName);
if ( flag == true )
{
System.out.println("That name exists!");
}
else
{
System.out.println("That name does not exist!");
}
}
public void remove (String theName)
{
}
Edit: I'm planning to use the Scanner in another function. Don't worry about it.
I'm not sure of if do you want to get the object of that array, but each object is indexed to that array (with full attributes), now you can remove it by using the following code,
public String removePerson(ArrayList<Person> arrayList,String name)
{
for(Person currentPerson:arrayList)
{
if(currentPerson.getName().equals(name))
{
arrayList.remove(currentPerson);
return "Removed successfully"
}
}
return "No record found for that person";
}
just pass the arrayList and the name of that person to this method
You should override the equals() and hashCode() methods in the Person class. This way you will define when two objects of this type will be considered equal. Then you can use list.contains(yourObject) to determine if that object is equal to any object in your list, this based on your equals() implementation.
Does this help you?
public void remove (String theName,ArrayList<Person> persons) {
for (int i = 0; i < persons.size();++i) {
if(persons[i].getName().equals(theName)) {
persons.remove(i);
}
}
}
Best regards, Nazar
I have an array list of objects which contains eg:
Name
Address
Phone
Many other properties...
I wish to remove some objects in this list, if some of the properties has the same value as other objects in the array list. I need to loop though the whole list and see if the Name, Address and Phone already exists in this list. I can not do a simple:
for (...)
if (!newlist.contains(element)) { newlist.add(element); }
As I only need to check specific properties are the same before adding the element to a new list.
Can anyone guide me in the right direction?
How about using Set with a custom Comparator ? Have your object class implement Comparable. In the compare method you can then write your test to match the objects exactly how you need it.
Create a Key Class let us say Employee.java with below code.
package com.innovation;
public class Employee {
private String name;
private String address;
private String phone;
public Employee() {
super();
}
public Employee(String name, String address, String phone) {
super();
this.name = name;
this.address = address;
this.phone = phone;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((address == null) ? 0 : address.hashCode());
result = prime * result + ((name == null) ? 0 : name.hashCode());
result = prime * result + ((phone == null) ? 0 : phone.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;
Employee other = (Employee) obj;
if (address == null) {
if (other.address != null)
return false;
} else if (!address.equals(other.address))
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
if (phone == null) {
if (other.phone != null)
return false;
} else if (!phone.equals(other.phone))
return false;
return true;
}
#Override
public String toString() {
return "Employee [name=" + name + ", address=" + address + ", phone="
+ phone + "]";
}
}
Now create a Client class where you want to apply your logic let us assume a class containing main method say Client.java
package com.innovation;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class Client {
public static void main(String[] args) {
Set<Employee> empSet = new HashSet<Employee>(populateList());
for (Employee employee : empSet)
{
System.out.println(employee);
}
}
public static List<Employee> populateList()
{
List<Employee> lsts = new ArrayList<Employee>();
lsts.add(new Employee("rais","gurgaon","123456"));
lsts.add(new Employee("alam","Delhi","123685"));
lsts.add(new Employee("shyam","Mumbai","1257456"));
lsts.add(new Employee("ramesh","Ahmadabad","196356"));
lsts.add(new Employee("rais","gurgaon","123456"));
lsts.add(new Employee("rais","gurgaon","123456"));
lsts.add(new Employee("rais","gurgaon","123456"));
return lsts;
}
}
You will see below out put. it is clearly visible that duplicate entry present in list is removed in set. it all magic of good implementation of equals and hashcode method.
Employee [name=rais, address=gurgaon, phone=123456]
Employee [name=ramesh, address=Ahmadabad, phone=196356]
Employee [name=alam, address=Delhi, phone=123685]
Employee [name=shyam, address=Mumbai, phone=1257456]
I've User object a shown below:
User.java:
public class User {
public String firstName;
public String 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 int hashCode() {
return (this.firstName.hashCode() + this.lastName.hashCode());
}
#Override
public boolean equals(Object obj) {
if(obj instanceof User) {
User temp = (User) obj;
if(this.firstName.equals(temp.firstName) && this.lastName.equals(temp.lastName)) {
return true;
}
}
return false;
}
}
And main program is shown below:
import java.util.*;
class pp {
public static void main(String[] args) {
List<User[]> a = new ArrayList<User[]>();
User[] u = new User[3];
u[0] = new User();
u[0].setFirstName("Mike"); u[0].setLastName("Jordon");
u[1] = new User();
u[1].setFirstName("Jack"); u[1].setLastName("Nicolson");
u[2] = new User();
u[2].setFirstName("Jack"); u[2].setLastName("Nicolson");
a.add(u);
Set<User[]> s = new HashSet<User[]>(a);
for (User[] ss : s) {
for (int i=0; i<ss.length; i++) {
System.out.println(ss[i].getFirstName() + " " + ss[i].getLastName());
}
}
}
}
I'm expecting output to be
Mike Jordon
Jack Nicolson
But somehow, its retaining duplicate object & printing as:
Mike Jordon
Jack Nicolson
Jack Nicolson
Can any one tell me what I'm missing??
Thanks!
Your equals method should be like :
#Override
public boolean equals(Object obj) {
if(obj instanceof User) {
User temp = (User) obj;
if(this.firstName.equals(temp.firstName) && this.lastName.equals(temp.lastName)) {
return true;
}
}
return false;
}
I have gone through your questions and understood the requirement. Please find the similar kind of code I have implemented and also successfully removed objects from a collection those having duplicate values.
#Snipet...
Employee.java
==============
package com.hcl;
public class Employee {
public String empid;
public String empname;
public double sal;
public int age;
public Employee(){
}
public Employee(String empid,String empname,double sal,int age){
this.empid = empid;
this.empname = empname;
this.sal = sal;
this.age = age;
}
public String getEmpid() {
return empid;
}
public void setEmpid(String empid) {
this.empid = empid;
}
public String getEmpname() {
return empname;
}
public void setEmpname(String empname) {
this.empname = empname;
}
public double getSal() {
return sal;
}
public void setSal(double sal) {
this.sal = sal;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
/**
* This override method playes a major role to remove duplicate values
*/
#Override
public int hashCode() {
return (this.empid.hashCode() + this.empname.hashCode()+String.valueOf(this.sal).hashCode()+String.valueOf(this.age).hashCode());
}
/**
* This override method plays a major role to remove duplicate values
*/
#Override
public boolean equals(Object obj) {
if(obj instanceof Employee) {
Employee temp = (Employee) obj;
if(this.empid.equals(temp.empid) && this.empname.equals(temp.empname) && String.valueOf(this.sal).equals(String.valueOf(temp.sal)) && String.valueOf(this.age).equals(String.valueOf(temp.age))) {
return true;
}
}
return false;
}
}
#Snipet..........
RemoveDuplicateObjects.java
=============================
package com.hcl;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class RemoveDuplicateObjects {
public static void main(String[] args) {
Employee emp1 = new Employee("1","bapi",1000,31);
Employee emp2 = new Employee("2","mano",2000,29);
Employee emp3 = new Employee("1","bapi",1000,31); // emp3 == emp1 duplicate object
Employee emp4 = new Employee("3","Rohan",3000,27);
Employee emp5 = new Employee("1","bapi",1000,31); // emp5 == emp3 == emp1 duplicate object
RemoveDuplicateObjects obj = new RemoveDuplicateObjects();
// empList contains objects having duplicate values. How to remove duplicate?
List<Employee> empList = new ArrayList<Employee>();
empList.add(emp1);
empList.add(emp2);
empList.add(emp3);
empList.add(emp4);
empList.add(emp5);
if(emp1.equals(emp2)){
System.out.println("emp1 and emp2 are equal");
}
if(emp1.equals(emp3)){
System.out.println("emp1 and emp3 are equal");
}
obj.removeDuplicate(empList);
}
// method is used for removing objects having duplicate values
private void removeDuplicate(List<Employee> empList) {
Set<Employee> empSet = new HashSet<Employee>();
empSet.addAll(empList);
for(Employee e: empSet){
System.out.println("id = "+e.getEmpid());
System.out.println("name = "+e.getEmpname());
System.out.println("sal = "+e.getSal());
System.out.println("age = "+e.getAge());
}
}
}
Done! Now you can run the program and analyze the solution.
I suppose you want this:
class pp {
public static void main(String[] args) {
Set<User> a = new HashSet<User>();
User u = new User();
u.setFirstName("Mike"); u.setLastName("Jordon");
a.add(u);
u = new User();
u.setFirstName("Jack"); u.setLastName("Nicolson");
a.add(u);
u = new User();
u.setFirstName("Jack"); u.setLastName("Nicolson");
a.add(u);
for (User ss : a) {
System.out.println(ss.getFirstName() + " " + ss.getLastName());
}
}
}
try this my friend :
Iterator i = a.iterator();
while (i.hasNext()) {
User u = (User) i.next();
boolean match = false;
Iterator j = a.iterator();
boolean once = true;
while (j.hasNext()) {
if(once){j.next();} // to skip own occurence only once
once = false;
User u2 = (User) j.next();
if (u.getFirstName().equals(u2.getFirstName())
&& u.getLastName().equals(u2.getLastName())) {
match = true;
}
}
if (!match) {
// print
}
}
Override the equals method as suggested by Jason.
Now for removing duplicates you need to use Set.
List allows duplicate values so you will always have duplicate values. Set doesnot allow duplicate value so it will solve your problem.
You're using a Set of arrays, where the set has one element, namely an array of three Users. Arrays don't enforce or check uniqueness, which is why you get the same User twice. If you removed the arrays altogether, and simply used a Set, you'd get the "unique" behaviour you want.
First you should use a Set to store objects instead of a array if you dont want duplicates. (Arrays and List do allow duplicate objects to be stores)
Second your equals methods should use String.equal method for comparison and should check for null values too to be on the safe side. I would use the IDE's auto generate feature for hashcode and equals methods always (i.e. Eclipse Source -> Generate hashCode() and equals()...)
#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;
User other = (User) 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;
}
and main method
public static void main(String[] args) {
List<Set<User>> a = new ArrayList<Set<User>>();
Set<User> set = new HashSet<User>();
User u = new User();
u.setFirstName("Mike"); u.setLastName("Jordon");
set.add(u);
u = new User();
u.setFirstName("Jack"); u.setLastName("Nicolson");
set.add(u);
u = new User();
u.setFirstName("Jack"); u.setLastName("Nicolson");
set.add(u);
a.add(set);
for (Set<User> ss : a) {
for (User user : ss) {
System.out.println(user.getFirstName() + " " + user.getLastName());
}
}
}
In general, you can add elements to a Set to remove duplicates. However, you don't want to add the entire array to the collection in general; you just want to add the individual elements, like so:
public static void main(String[] args) {
Set<User> a = new HashSet<User>();
User[] u = new User[3];
u[0] = new User();
u[0].setFirstName("Mike"); u[0].setLastName("Jordon");
u[1] = new User();
u[1].setFirstName("Jack"); u[1].setLastName("Nicolson");
u[2] = new User();
u[2].setFirstName("Jack"); u[2].setLastName("Nicolson");
// Add each of the users to the Set. Note that there are three.
for (User user : u) {
a.add(u);
}
// Get the results back as an array. Note that this will have two.
User[] duplicatesRemoved = new User[0];
a.toArray(duplicatesRemoved);
}
Hi you can write a method in pp class in order to remove duplicate elements from the user array as follows :
private User[] getUserArrayWithoutDuplicates(User[] a) {
int count = a.length;
Set<User> tempset = new HashSet<User>();
for (int i = 0; i < count; i++) {
User[] user = a;
int arraysize = user.length;
for (int j = 0; j < arraysize; j++)
tempset.add(user[j]);
}
User[] usr = new User[tempset.size()];
Iterator<User> tempIterator = tempset.iterator();
int p = 0;
while (tempIterator.hasNext()) {
User user = tempIterator.next();
usr[p] = new User();
usr[p].setFirstName(user.firstName);
usr[p].setLastName(user.lastName);
p++;
}
return usr;
}
This method will remove the duplicate entries from User array and return the User array without duplicate entries.