I have two lists of Personne: listOne and listTwo.
Personne is:
public class Personne{
private String name;
private Favorite favorite;
private Collection<Number> numbers;
}
public class Favorite{
private String id;
private String name;
...
}
For each item, I want to merge the two lists if the favorite name and id of the first list equals the favorite name and id of the second list, and then merge the second list to first.
This is a part of my treatement and what i means by merge (its not create an other list ) :
if my condition is true i want to take item of my first list :
item.setNumbers(item2.getnumbers);
What is the best way to do this with Java 7?
I'd try iterating over listOne, check for each desired item if it's in listTwo and in that case add the entries from listOne and listTwo to a new list.
Something like
https://gist.github.com/a2465b03fb7503f9c8190ab72c328c10
As far as I have understood, we want to get a list containing all unique elements of both lists without duplicates.
First let's create an equals() method for the classes which is needed for ArrayList.contains() method to function properly:
class Favorite {
...
private boolean equals(Favorite other) {
int i = id.compareTo(other.id);
if (i != 0) return false;
return (name.compareTo(other.name) == 0);
}
class Personnel {
...
private boolean equals(Personnel other) {
int i = name.compareTo(other.name);
if (i != 0) return false;
return favorite.equals(other.favorite);
}
Since there is no guarantee that input lists are sorted, we can write merging method like this:
public List<Personnel> merge(List<Personnel> listOne, List<Personnel> listTwo) {
List<Personnel> result = new ArrayList<>(listOne);
for (Personnel p : listTwo) {
if (!result.contains(p)) {
result.add(p);
}
}
return result;
}
Related
I have a little problem that is driving me crazy.
I have a
List<Integer> with ids.
List<ObjectA> with 3 variables:
an id, and two string
I have to sort the second list by putting at the top the elements with id contained in the first list, then by string asc and by the second string asc.
What is the easiest way to make this work? I am trying to use the .sort(), Comparators etc.
An example:
#Getter
#Setter
public class ObjectA {
private Integer id;
private String code;
private String name;
}
// comparator:
static class SortByCode implements Comparator<ObjectA> {
public int compare(ObjectA a, ObjectA b) {
String as = a.getCode();
String bs = b.getCode();
return as.compareTo(bs);
}
}
static class SortByName implements Comparator<ObjectA> {
public int compare(ObjectA a, ObjectA b) {
String as = a.getName();
String bs = b.getName();
return as.compareTo(bs);
}
}
// then in service:
List<Integer> idsPreferred = new ArrayList<>();
List<ObjectA> listObj = new ArrayList<>();
idsPreferred = .... add preferred ids;
listObj = .... add objects;
listObj.sort(new SortByCode()).thenComparing(new SortByName());
With this i sort by code and by name - but i need to add the sorting by the first list - I need the elements that have an id contained in the List to come before the others.
I suppose something like this using chained comparing by extracted key:
listObj.sort(Comparator.comparing(o -> !idsPreferred.contains(((ObjectA) o).getId()))
.thenComparing(o -> ((ObjectA) o).getId())
.thenComparing(o -> ((ObjectA) o).getCode())
.thenComparing(o -> ((ObjectA) o).getName()));
or
listObj.sort(Comparator.comparing(ObjectA::getId,
(id1,id2)-> {if (!((idsPreferred.contains(id1))^idsPreferred.contains(id2)))
return 0;
else return (idsPreferred.contains(id2))?1:-1;})
.thenComparing(ObjectA::getId)
.thenComparing(ObjectA::getCode)
.thenComparing(ObjectA::getName));
The solution will involve 2 steps-
check id of objects from second list, which are present in first list.
Sort the contained objects using either of the solutions suggested- How to sort List of objects by some property
I have two Lists containing objects of this class:
public class SchoolObj
{
private String name;
private String school;
public SchoolObj()
{
this(null, null);
}
public SchoolObj(String nameStr, String schoolStr)
{
this.setName(nameStr);
this.setSchool(schoolStr);
}
public String getName()
{
return this.name;
}
public void setName(String name)
{
this.name = name;
}
public String getSchool()
{
return this.school;
}
public void setSchool(String school)
{
this.school = school;
}
#Override
public String toString()
{
return this.getName() + ' ' + this.getSchool();
}
}
I want to compare the objects in those two lists by name and school. If they are equal I need to create a new List containing those SchoolObj objects which are found in both Lists.
I know we can use two for loops and do it is in the createSharedListViaLoop method below.
My question is, how can I accomplish the same thing with Java streams?
I tried with createSharedListViaStream below, but it is not working as expected.
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
public class StreamTest
{
public static void main(String[] args)
{
List<SchoolObj> listOne = new ArrayList<SchoolObj>();
// TODO: Add sample data to listOne.
listOne.add(new SchoolObj("nameA", "schoolX"));
listOne.add(new SchoolObj("nameC", "schoolZ"));
List<SchoolObj> listTwo = new ArrayList<SchoolObj>();
// TODO: Add sample data to listTwo.
listTwo.add(new SchoolObj("nameA", "schoolX"));
listTwo.add(new SchoolObj("nameB", "schoolY"));
// Print results from loop method.
System.out.println("Results from loop method:");
List<SchoolObj> resultsViaLoop = StreamTest.createSharedListViaLoop(listOne, listTwo);
for (SchoolObj obj : resultsViaLoop)
{
System.out.println(obj);
}
// Print results from stream method.
System.out.println("Results from stream method:");
List<SchoolObj> resultsViaStream = StreamTest.createSharedListViaStream(listOne, listTwo);
for (SchoolObj obj : resultsViaStream)
{
System.out.println(obj);
}
}
public static List<SchoolObj> createSharedListViaLoop(List<SchoolObj> listOne, List<SchoolObj> listTwo)
{
List<SchoolObj> result = new ArrayList<SchoolObj>();
for (SchoolObj one : listOne)
{
for (SchoolObj two : listTwo)
{
if (one.getName().equals(two.getName()) && one.getSchool().equals(two.getSchool()))
{
result.add(one);
}
}
}
return result;
}
public static List<SchoolObj> createSharedListViaStream(List<SchoolObj> listOne, List<SchoolObj> listTwo)
{
List<SchoolObj> listOneList = listOne.stream().filter(two -> listTwo.stream()
.anyMatch(one -> one.getName().equals(two.getName()) && two.getSchool().equals(one.getSchool())))
.collect(Collectors.toList());
return listOneList;
}
}
Let's run through each part of the code. First, createSharedListViaStream:
public static List<SchoolObj> createSharedListViaStream(List<SchoolObj> listOne, List<SchoolObj> listTwo)
{
// We create a stream of elements from the first list.
List<SchoolObj> listOneList = listOne.stream()
// We select any elements such that in the stream of elements from the second list
.filter(two -> listTwo.stream()
// there is an element that has the same name and school as this element,
.anyMatch(one -> one.getName().equals(two.getName())
&& two.getSchool().equals(one.getSchool())))
// and collect all matching elements from the first list into a new list.
.collect(Collectors.toList());
// We return the collected list.
return listOneList;
}
After running through the code, it does exactly what you want it to do. Now, let's run through createSharedListViaLoop:
public static List<SchoolObj> createSharedListViaLoop(List<SchoolObj> listOne, List<SchoolObj> listTwo)
{
// We build up a result by...
List<SchoolObj> result = new ArrayList<SchoolObj>();
// going through each element in the first list,
for (SchoolObj one : listOne)
{
// going through each element in the second list,
for (SchoolObj two : listTwo)
{
// and collecting the first list's element if it matches the second list's element.
if (one.getName().equals(two.getName()) && one.getSchool().equals(two.getSchool()))
{
result.add(one);
}
}
}
// We return the collected list
return result;
}
So far, so good... right? In fact, your code in createSharedListViaStream is fundamentally correct; instead, it is your createSharedListViaLoop that may be causing discrepancies in output.
Think about the following set of inputs:
List1 = [SchoolObj("nameA","SchoolX"), SchoolObj("nameC","SchoolZ")]
List2 = [SchoolObj("nameA","SchoolX"), SchoolObj("nameA","SchoolX"), SchoolObj("nameB","SchoolY")]
Here, createSharedListViaStream will return the only element of the first list that appears in both lists: SchoolObj("nameA","SchoolX"). However, createSharedListViaLoop will return the following list: [SchoolObj("nameA","SchoolX"),SchoolObj("nameA","SchoolX")]. More precisely, createSharedListViaLoop will collect the correct object, but it will do so twice. I suspect this to be the reason for the output of createSharedListViaStream to be "incorrect" based on comparison to the output of createSharedListViaLoop.
The reason that createSharedListViaLoop does this duplication is based on the lack of termination of its inner for loop. Although we iterate over all elements of the first list to check if they are present in the second, finding a single match will suffice to add the element to the result. We can avoid redundant element addition by changing the inner loop to the following:
for (SchoolObj one : listOne)
{
for (SchoolObj two : listTwo)
{
if (one.getName().equals(two.getName()) && one.getSchool().equals(two.getSchool()))
{
result.add(one);
break;
}
}
}
Additionally, if you don't want duplicate Objects in your list (by location in memory), you can use distinct like so:
List<SchoolObj> result = ...;
result = result.stream().distinct().collect(Collectors.toList());
As a final caution, the above will keep the results distinct in the following scenario:
List<SchoolObj> list = new ArrayList<>();
SchoolObj duplicate = new SchoolObj("nameC", "schoolD");
listOne.add(duplicate);
listOne.add(duplicate);
list.stream().distinct().forEach(System.out::println);
// prints:
// nameC schoolD
However, it will not work in the following scenario, unless you override the equals method for SchoolObj:
List<SchoolObj> list = new ArrayList<>();
listOne.add(new SchoolObj("nameC", "schoolD"));
listOne.add(new SchoolObj("nameC", "schoolD"));
list.stream().distinct().forEach(System.out::println);
// prints (unless Object::equals overridden)
// nameC schoolD
// nameC schoolD
You can filter in one list if contains in another list then collect.
List<SchoolObj> listCommon = listTwo.stream()
.filter(e -> listOne.contains(e))
.collect(Collectors.toList());
You need to override equals() method in SchoolObj class. contains() method you will uses the equals() method to evaluate if two objects are the same.
#Override
public boolean equals(Object o) {
if (!(o instanceof SchoolObj))
return false;
SchoolObj n = (SchoolObj) o;
return n.name.equals(name) && n.school.equals(school);
}
But better solution is to use Set for one list and filter in another list to collect if contains in Set. Set#contains takes O(1) which is faster.
Set<SchoolObj> setOne = new HashSet<>(listOne);
List<SchoolObj> listCommon = listTwo.stream()
.filter(e -> setOne.contains(e))
.collect(Collectors.toList());
You need to override hashCode() method also along with equals() in SchoolObj class for Set#contains.(assuming name and school can't be null)
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + name.hashCode();
result = prime * result + school.hashCode();
return result;
}
Here you will get details how to override equals and hashCode in a better way
In my case I had Two lists. I compared both lists having common emails and collected the objects like this:
List<TUsers> comparedUsersOnEmail = tUsers.stream().filter(o1 -> userR.stream()
.anyMatch(o2->o2.getEmail().equals(o1.getEmail()))).collect(Collectors.toList());
Currently creating a tableview using JavaFX and came accross this problem where it would simply append the last element of the array (As all the other elements get overrwritten ..)
public void companyTable() {
for(CompanyData s: companydataList()){
companyDataTableView.getItems().setAll(s);
}
}
Where companyDataList is:
private List<CompanyData> companydataList(){
CompanyData company = new CompanyData("test",9,1);
for(String i : sim.getCompanyNames()) {
company.setPFCompanyName(i);
}
for(int j : sim.getCompanyValues()) {
company.setPFShareValues(j);
}
List<CompanyData> companydata = new ArrayList<>();
companydata.add(company);
return companydata;
}
The data gets added to this (Setters and getters of Strings)
private final StringProperty PFCompanyName;
private final IntegerProperty PFShareValues;
public CompanyData(String CompanyName, int ShareValue, int ClosingPence) {
this.PFCompanyName = new SimpleStringProperty(CompanyName);
this.PFShareValues = new SimpleIntegerProperty(ShareValue);
}
public String getPFCompanyName() {
return PFCompanyName.get();
}
public StringProperty PFCompanyNameProperty() {
return PFCompanyName;
}
public void setPFCompanyName(String PFCompanyName) {
this.PFCompanyName.set(PFCompanyName);
}
public int getPFShareValues(int j) {
return PFShareValues.get();
}
public IntegerProperty PFShareValuesProperty() {
return PFShareValues;
}
public void setPFShareValues(int PFShareValues) {
this.PFShareValues.set(PFShareValues);
}
Currently the output is:
CompanyName CompanyValue
Samsung 1093
But what I desire is:
CompanyName CompanyValue
Nokia 3
Apple 1
HTC 9
Samsung 1093
The method setAll(...) replaces all the elements currently in the list with the ones you provide (it "sets them all"). So each time you iterate through your loop, you replace all the elements with the current one. At the end you will just have one element in the table.
An ObservableList is a subtype of the standard java.util.List, so you can call any of the standard list methods. E.g. you can just add each element instead:
public void companyTable() {
for(CompanyData s: companydataList()){
companyDataTableView.getItems().add(s);
}
}
Of course, you don't really need to write the loop yourself, you can just add them all:
public void companyTable() {
companyDataTableView.getItems().addAll(companydataList());
}
or, if it's what you need, set them all:
public void companyTable() {
companyDataTableView.getItems().setAll(companydataList());
}
Furthermore, your companydataList() method only creates one CompanyData instance, and then constantly changes it. Here is your current implementation, with comments explaining what each line you wrote does:
private List<CompanyData> companydataList(){
// create a single instance:
CompanyData company = new CompanyData("test",9,1);
// repeatedly change the name of that instance:
for(String i : sim.getCompanyNames()) {
company.setPFCompanyName(i);
}
// repeatedly change the value of that instance:
for(int j : sim.getCompanyValues()) {
company.setPFShareValues(j);
}
// create an empty list:
List<CompanyData> companydata = new ArrayList<>();
// add one object to the list
companydata.add(company);
// return the list containing the single object:
return companydata;
}
You need to create a CompanyData instance for each of the name/value pairs, and add each instance to the list. Assuming sim.getCompanyNames() and sim.getCompanyValues() return lists (or arrays; I will assume they are lists) of the same length, you need to do something like
private List<CompanyData> companydataList(){
List<String> companyNames = sim.getCompanyNames();
List<Integer> companyValues = sim.getCompanyValues();
List<CompanyData> companydata = new ArrayList<>();
for (int i = 0 ; i < companyNames.size(); i++) {
String name = companyNames.get(i);
int value = companyValues.get(i);
CompanyData company = new CompanyData();
company.setPFCompanyName(name);
company.setPFShareValues(value);
companydata.add(company);
}
return companydata;
}
Obviously, it would be far more sensible to have sim, which I assume is some kind of data accessor, return a List<CompanyData> directly in the first place, instead of two different lists for the different properties.
I have an object list that retrieves multiple values from a database, like so:
List<Object> listRequest = daoManager.getLaptopsForRequest(BigInteger.valueOf(itemTransItem.getAssetType().getId()), BigInteger.valueOf(approverId));
The result of which looks like this (printed out on the console, via for each):
{asset_type_id=1, inventory_id=1, from_dt=2015-09-18 18:04:55.77, id=1, asset_id=1, status=1, thru_dt=null}
{asset_type_id=1, inventory_id=1, from_dt=2015-09-18 18:04:55.77, id=2, asset_id=2, status=1, thru_dt=null}
{asset_type_id=1, inventory_id=1, from_dt=2015-09-18 18:04:55.77, id=3, asset_id=3, status=1, thru_dt=null}
What's the quickest and/or most efficient way to get only the object where asset_id = 2, or an array of asset_id (1 and 2), and putting the results in another array?
I contemplated casting each object as a string, and then turning each string into an array (split by the comma), and then turning each item of the array into a further array (or a hashmap) by using the =, but that seems like a long, long, complex way of nested for loops that might fail (see comparing array of assets).
Perhaps there's another quicker / less complex way to do this that I'm missing? Any suggestions? Thanks.
EDIT: For reference, here's the getLaptopsForRequest function:
public List getLaptopsForRequest(BigInteger asset_type_id, BigInteger party_id){
SQLQuery query = sessionFactory.getCurrentSession().createSQLQuery(laptopsForRequestSql);
query.setResultTransformer(Criteria.ALIAS_TO_ENTITY_MAP);
List forRequest = query.setBigInteger(0, asset_type_id).setBigInteger(1, party_id).list();
return forRequest;
}
It returns a list of the results of the query. As this code has been in place, I'm not allowed to edit it.
A quick and dirty solution would be to match each item against regex ^.*asset_id=([0-9]+).*$.
If what you're getting from that method is indeed a list of Strings containing those JSONs, you could create a model class and use a JSON serializer like GSON or Jackson to read the strings into Java objects, and then you could work with them.
What you are trying to do basically is to filter a list of objects. You could implement the Filter Pattern writing your own Iterator for the list.
Just extends this class to implement your own filter.
public abstract class Filter<T> {
public abstract boolean passes(T object);
public Iterator<T> filter(Iterator<T> iterator) {
return new FilterIterator(iterator);
}
public Iterable<T> filter(Iterable<T> iterable) {
return new Iterable<T>() {
public Iterator<T> iterator() {
return filter(iterable.iterator());
}
};
}
private class FilterIterator implements Iterator<T> {
private Iterator<T> iterator;
private T next;
private FilterIterator(Iterator<T> iterator) {
this.iterator = iterator;
toNext();
}
public boolean hasNext() {
return next != null;
}
public T next() {
if (next == null)
throw new NoSuchElementException();
T returnValue = next;
toNext();
return returnValue;
}
public void remove() {
throw new UnsupportedOperationException();
}
private void toNext() {
next = null;
while (iterator.hasNext()) {
T item = iterator.next();
if (item != null && passes(item)) {
next = item;
break;
}
}
}
}
}
and then use it in this way:
List<MyObject> newList = new ArrayList<MyObject>();
for(MyObject obj : filter.filter(listObjs) ){
newList.add(obj);
}
Assuming your objects have getter et setter methods.
Only the object where asset_id = "2", asset_id here being a string
listRequest.stream().filter(e -> e.getAssetId() == "2" ).toArray();
We need to compare 2 arraylists of different objects having some common fields, and then store the matching rows to a new arraylist. I have searched for solutions, but wasn't able to get what I need.
List<Person> personList = new ArrayList<Person>();
Person:
private String firstName;
private String lastName;
private String street1;
private String street2;
private String city;
private String stateCode;
private String zipCode;
List<PersonNpi> npiList = new ArrayList<PersonNpi>();
PersonNpi:
private String name;
private String npi;
private Address address;
So I need to check if the name & address in the PersonNpi object in the PersonNpiList match to a Person object in the PersonList, and if yes save the Person details + Npi to a new Arraylist<Employee>
Hope I'm clear on the question. Please let me know on how to solve this efficiently.
Thanks
Harry
EDIT:
I need to save the non-matching rows (on the first arraylist) as well to another list. Do I need to have another loop or can I do it on the same For loop? Anyone please?
Since I don't see any superclasses from which they extend, you have to manually iterate through your lists. I am assuming a lot, for instance that you have getters and setters for your attributes, that PersonNpi.name is more or less the same as Person.firstname + Person.lastname, that you have some function in Address like boolean checkEquality(String street1, String street2, String city, String state, String zip), that your Person class has a getName() method to compare with PersonNpis. In that case, loop through the first array, and check for every item if the second has anything equal to it.
ArrayList<Employee> employees = new ArrayList<Employee>();
for(Person person : personList) {
for(PersonNpi personNpi : npiList) {
if (person.getName().equals(personNpi.getName()) &&
person.getAddress().checkEquality(...address parts here...)) {
employees.add(new Employee(person, personNpi));
}
}
}
Again, I made a lot of assumptions, also the one that you have an Employee constructor which just requires the Person and the PersonNpi, and gets the required information accordingly.
You should elaborate more, use superclasses, and use the contains() function. In other words, make comparing the Person and the PersonNpi easier through a function.
Edit: your second question is highly, if not extremely dependant on your further implementation of Employee, Person and PersonNpi. For now, I'll yet again assume you have some methods that verify equality between Employee, Person and PersonNpi.
I'd suggest to not do the checking in one loop, since you have two ArrayLists which are ran through. The PersonNpi-list is ran through for every record in the first List. So what might happen is after we checked everything, a few Persons are left unmatched, and a few PersonNpis are left unmatched, since we don't flag which Persons and PersonNpis we've matched.
In conclusion: for easiness' sake, just add this part:
ArrayList<Object> nonMatchedPersons = new ArrayList<Object>();
for (Person person : personList)
if (!employees.contains(person))
nonMatchedPersons.add(person);
for (PersonNpi personNpi : npiList)
if (!employees.contains(personNpi))
nonMatchedPersons.add(personNpi);
This method does require you to implement the equals(Object) method for all 3 person classes, which you might consider putting beneath a superclass like Human. In that case, you can make the Object ArrayList into a ArrayList<Human>
With one loop (requires equals(Object) method for the 3 person classes):
List<Employee> employees = new ArrayList<Employee>();
ArrayList<Object> nonMatchedPersons = new ArrayList<Object>();
Iterator<Person> personIterator = personList.iterator();
while (personIterator.hasNext()) {
Iterator<PersonNpi> npiIterator = npiList.iterator();
while(npiIterator.hasNext()) {
Person person = personIterator.next();
PersonNpi personNpi = npiIterator.next();
if (person.equals(personNpi)) {
employees.add(new Employee(person, personNpi));
personIterator.remove();
npiIterator.remove();
}
}
}
nonMatchedPersons.addAll(personList);
nonMatchedPersons.addAll(npiList);
Explanation: we loop with Iterators through both lists, to enable us to remove from the list while iterating. So in the personList and the npiList, only the singles remain, as we add doubles to the Employee-list, instantly removing them from the other two lists. We add the remaining singles in the two lists to our nonMatchedPerson-list with the addAll method.
Edit2: If you can't edit those classes for whatever reason, make 3 wrapper classes, something like:
public class PersonWrapper {
private Person person;
public PersonWrapper(Person person) {
this.person = person;
}
#override
public boolean equals(Object other) {
if (other == null)
return false;
if (other instanceof PersonWrapper) {
//etc etc, check for equality with other wrappers.
...
}
}
}
If you choose to use this approach, change this line in the loop:
if (person.equals(personNpi)) {
to this:
if (new PersonWrapper(person).equals(new PersonNpiWrapper(personNpi))) {
Using this, you can still implement your own equals() method.
Another solution could be that you make a static method like this:
public static boolean equals(Object this, Object that) {
if (this instanceof Person || this instanceof PersonNpi) //et cetera, et cetera
return true;
return false;
}
Now just call Person.equals(person, personNpi), assuming you put the method in the class Person.
If you implement equals to compare the values under question, you can then use contains to see if object is in other list.
Otherwise you'll have to manually iterate though lists, and check each object.
And if you using jdk8 Lambda, you could do something like this (compiles and runs btw, with correct jdk) :
public static void main(String args[]) throws ParseException {
TransformService transformService = (inputs1, inputs2) -> {
Collection<String> results = new ArrayList<>();
for (String str : inputs1) {
if (inputs2.contains(str)) {
results.add(str);
}
}
return results;
};
Collection<String> inputs1 = new ArrayList<String>(3) {{
add("lemon");
add("cheese");
add("orange");
}};
Collection<String> inputs2 = new
ArrayList<String>(3) {{
add("apple");
add("random");
add("cheese");
}};
Collection<String> results = transformService.transform(inputs1, inputs2);
for (String result : results) {
System.out.println(result);
}
}
public interface TransformService {
Collection<String> transform(Collection<String> inputs1, Collection<String> inputs2);
}
Something like this should work. It assumes that you have a way of constructing an Employee from a Person and a PersonNpi. Also, since you don't tell the structure of an Address, I'll leave it to you to write the address matching logic.
public List<Employee> findCommonElements(List<Person> list1,
List<PersonNpi> list2)
{
List<Employee> common = new ArrayList<Employee>();
for (Person p1 : list1) {
PersonNpi p2 = find(list2, p1);
if (p2 != null) {
common.add(new Employee(p1, p2));
}
}
}
private PersonNpi find(List<PersonNpi> list, Person p) {
for (PersonNpi p2 : list) {
if (matches(p, p2)) {
return p2;
}
}
return null;
}
private boolean matches(Person p1, PersonNpi p2) {
return /* logic for comparing name and address info */;
}
This is an O(n2) operation. You could speed this up considerably by sorting both arrays by name and address. The sorting operation is O(n log(n)) and the comparison could then be implemented as an O(n) operation.
Use HashMap to store the first list PersonNpiList. Use map.get(Person) == null to check whether the person is in the hash map.