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 ?
Asked
Active
Viewed 92 times
0
-
1First, override the `equals()` and `hashCode()` methods in the `User` class. – Mr. Polywhirl Apr 27 '16 at 14:51
-
Yes, you can use two for loops. I'm not sure about a function that already exists. If using two for loops works "good enough" use that. – Retro Gamer Apr 27 '16 at 14:57
3 Answers
2
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.

Aaron
- 24,009
- 2
- 33
- 57
2
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());
}

Mr. Polywhirl
- 42,981
- 12
- 84
- 132
-
Thank you, can you please tell me what is the final int prime = 31; ? I don't get it. – user3235881 Apr 28 '16 at 11:24
-
@user3235881 It is the default value for a prime multiplier provided by Eclipse IDE. For the reasoning behind this, check out: [***Why does Java's hashCode() in String use 31 as a multiplier?***](http://stackoverflow.com/questions/299304/why-does-javas-hashcode-in-string-use-31-as-a-multiplier). – Mr. Polywhirl Apr 28 '16 at 11:28
-
@user3235881 In my example above, you will always get 2 in the console, unless you changed something. There is nothing wrong with the equals. It is using `String.equals()` which compares names lexicographically. – Mr. Polywhirl Apr 28 '16 at 11:56
0
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;
}

Adnan Isajbegovic
- 2,227
- 17
- 27