Iterate ArrayList and get match items Id - java

I have an ArrayList which contains data like profId, firstname, lastname, age.
Now I have a lastname and firstname, which gets from user form side. Now I want to compare them with an ArrayList. If both match, I want to retrieve "respective profId".
e.g arraylist contains data like
profId lastname fistname age
1 roy sam 25
2 ryob arnav 30
Now user will type lastname and firstname as roy and sam respectively. I will get this data by their getter methods.
Now, how should I compare these 2 names with the ArrayList so that I will get the perfect profid of him as:
'1'.
I am trying to compare by this way.
// existPatList is arraylist patfamily is object of Family from where I will get users value
for(Family p : existPatList) {
System.out.println("Last name" +p.getLastName());
System.out.println("First name"+p.getFirstName());
if(p.getLastName().equalsIgnoreCase(patFamily.getLastName())) {
System.out.println("got it");
}
}
How can I solve this problem?

Use a && in your if condition with both firstName and lastName.
for(Family p : existPatList) {
System.out.println("Last name" +p.getLastName());
System.out.println("First name"+p.getFirstName());
if(p.getFirstName().equalsIgnoreCase(patFamily.getFirstName()) && p.getLastName().equalsIgnoreCase(patFamily.getLastName())) {
System.out.println("got it");
}
}
To get profId replace your line:
System.out.println("got it");
with
System.out.println(p.getProfId); //or do whatever you wanna do with profId
I consider here the you getters also has a get method for profId, that is getProfId()

Related

Iterate through list and add to list without incurring ConcurrentModificationException - Java

Apologies, this has been done to death but I am really struggling to implement a solution to this problem and I am quite new to Java.
I need to be able to call a method which basically allows a Person object to be added to a list.
The main problem I have encountered whilst trying to implement a solution is a 'ConcurrentModificationException' which is understandable given I have been trying to update the list whilst in the middle of a for each loop.
So, I have come up with the following solution which prevents the 'ConcurrentModificationException' but my solution doesn't work properly and seems overcomplicated - see following code snippet of method:
public void addPerson(Person aPerson) {
// tempPersons list for temporarily storing Person objects
tempPersons = new ArrayList<>();
// if persons list is initially empty, add aPerson object to it
if (persons.isEmpty()) {
persons.add(aPerson);
}
// if persons list is not initially empty
if (!persons.isEmpty()) {
// loop through persons list
for (Person anotherPerson : persons) {
// if persons list anotherPerson first name is the same as the aPerson first name, print message
if (anotherPerson.getFirstName().equals(aPerson.getFirstName())) {
System.out.println("The Person " + aPerson.getFirstName() +
" is already entered in the list");
}
// otherwise add the aPerson object to the tempPersons list
else {
tempPersons.add(aPerson);
}
}
// once out of loop, add the tempPersons list to the persons list
persons.addAll(tempPersons);
// create new tempPersons2 list based on a hashset of the persons list so there are no duplicates
List<Person> tempPersons2 = new ArrayList<>(
new HashSet<>(persons));
// assign tempPersons2 list without duplicates to persons list
persons = tempPersons2;
}
}
So, if for example I call the above addPerson method 4 separate times with a mixture of unique and duplicate objects (aPerson param), the method correctly identifies that there is already an object with the same first name in there but the persons list always seems to end up with a duplicate object (first name) in there e.g. if I have the following objects:
Person1
FirstName = Bob
Person2
FirstName = Jan
Person3
FirsName = Bob
Person4
FirstName = Ann
Then I make the following method call 4 separate times:
addPerson(Person1);
addPerson(Person2);
addPerson(Person3);
addPerson(Person4);
When I call a print method, I get the following output:
The Person Bob is already entered in the list
Jan
Ann
Bob
Bob
I would expect the following:
The Person Bob is already present
Jan
Ann
Bob
Apologies for all the waffle and what is probably a really simple solution to most of you but I have been stuck on this for a couple of days.
Similar article can be found here but I am still struggling.
Adding elements to a collection during iteration
Without changing your code too much:
public void addPerson(Person person) {
// The guard is more or less a premature optimization and should be removed.
if (persons.isEmpty()) {
persons.add(person);
return;
}
for (Person anotherPerson : persons) {
if (anotherPerson.getFirstName().equals(person.getFirstName())) {
System.out.println("The Person " + person.getFirstName() +
" is already entered in the list");
return;
}
}
persons.add(person);
}
This would exit the method when a match is found, if there are no matches the person is simply added after the loop. Note the return in the first check.
Optimizations of this code could be using a Map or Set to speed up the contains check; also just using anyMatch on persons would lead to a more elegant solution.
The duplicates are caused by your for loop and it's else condition. If Bob and Jan is in your collection and you add a second Bob then Jan won't be equal to Bob and your else path is executed adding a duplicate to your final persons List.
You can use Set instead of list which will satisfy your need and implement the comparator or comparable interface for person comparison

Java: 1 key with multiple values using data structure

I have a list of objects having code and user name. I can get the code and username with getCode() and getUserName(). I can think of using MultiMap if I must display only code and list of usernames associated for each code. But how to display all three details (code, usercount, usernames) with different data types using Java?
Code - String (Key)
UserCount - Integer (Value)
UserNames - List (Value)
How to display in the below format using Java?
Code UserCount UserNames
Abc 2 Jack, Mary
Def 1 Steven
Ghi 3 James, Ray, Jim
If I understand, you have a List<YourObject> where YourObject is the class :
public class YourObject {
public String code;
public String userName;
// getters and constructor(s)
}
When you say :
I must display only code and list of usernames associated for each code
It means that in your List<YourObject>, if two objects A and B have the same code value X, you want to display something like "Code X ; usernames = [A.getUserName(), B.getUserName()]" ?
But you also want to add a userCount attribute which is the size of the usernames list (in my above exemple : 2).
I think you can create a utility method that takes your List<YourObject> as parameter and return a Map<String,List<String>> where the key string is the code and the List of strings is the usernames.
Something like : (Sorry for the stream version, I was too lazy to write more lines) :
public static Map<String,List<String>> process(List<YourObject> list) {
return list.stream().collect(Collectors.toMap(YourObject::getCode, x -> list.stream().filter(e -> x.getCode().equals(e.getCode())).map(YourObject::getUserName).collect(Collectors.toList()), (x,y) -> x));
}
The display you wanted :
process(yourList).forEach((k,v) -> {
System.out.println("Code : " + k + " | userCount :" + v.size() + " | Usernames =" + v)
});

Processing HashMap of crew details

Enviroment: Java 7
I have a hashmap 'pdf' of Aircrew details that has the following key structure:
public static Map<String, String> pdf;
PilotName JONES
PilotFirstname Jim
PilotID 12345
PilotLicense AAD987
PilotDOB 12/12/2001
PilotGender Male
PilotEthnicity
PilotAddress 123 Any Street
CopilotName SMITH
CopilotFirstname Thomas
CopilotID 987654
CopilotLicense AAB9475
CopilotAddress 456 Any Street
CopilotDOB 12/03/1987
CopilotGender Male
CopilotEthnicity European
CabinManagerSurname
CabinManagerFirstName BROWN
CabinManagerID 48573
CabinManagerDOB
CabinManagerGender
CabinManagerEthnicity
CabinManagerAddress
Hostess1Surname
Hostess1FirstName
HostessID
Hostess1DOB
Hostess1Gender
Hostess1Ethnicity
Hostess1Address 789 Any Street
Hostess2Surname EDWARDS
Hostess2FirstName Mary
HostessID 475804
Hostess2DOB 11/10/1990
Hostess2Gender Female
Hostess2Ethnicity European
Hostess2Address
Hostess3Surname
Hostess3FirstName
Hostess3ID 489282
Hostess3DOB
Hostess3Gender
Hostess3Ethnicity
Hostess3Address
NB: The field names for crew and pilots are different (Surname/Name Firstname/FirstName).
I want to test if any of certain fields are not empty then call createPerson() method.
The fields to be tested differ for Cabin Crew from Pilots.
I made this attempt but the code is ugly:
List<String> pilotRoles = ["Pilot", "Copilot"];
List<String> cabinRoles = ["CabinManager", "Hostess1", "Hostess2", "Hostess3"];
for (String role : pilotRoles) {
if ( String.isNotNullOrEmpty(pdf.get(pilotRole +"Name")) || String.isNotNullOrEmpty(pdf.get(pilotRole +"Firstname")) || String.isNotNullOrEmpty(pdf.get(pilotRole +"ID")) || String.isNotNullOrEmpty(pdf.get(pilotRole +"License"))) {
listPeople.add(createPerson(pdf, pilotRole));
for (String role : cabinRoles) {
if ( String.isNotNullOrEmpty(pdf.get(cabinRole +"Surname")) || String.isNotNullOrEmpty(pdf.get(cabinRole +"FirstName")) || String.isNotNullOrEmpty(pdf.get(cabinRole +"ID")) ) {
listPeople.add(createPerson(pdf, cabinRole));
For the above data the createPerson routine would be entered for both pilots as at least 1 of the tested fields is not null or empty.
The createPerson routine would NOT be entered for hostess1 and all of the tested fields are null or empty.
Is there a more elegant way? If so how.
I'd try something like this: In addition to your lists of roles, create an additional list that holds the names of all attributes, like "Name" etc.
Then you can then create a function to filter your roles for fields that are missing in your pdf map, like this:
private List<String> getRolesOfMissingUsers(Map<String, String> pdf, List<String> roles, List<String> attributes) {
return roles.stream().filter(role -> attributes.stream().map(attribute -> role + attribute)
.anyMatch(roleAttribute -> StringUtils.isNotBlank(pdf.get(roleAttribute))))
.collect(toList());
}
You can then use the result of this method to create your missing users. Here is an example just for your pilot rules:
for (String role : getRolesOfMissingUsers(pdf, pilotRoles, Arrays.asList("Name", "Firstname", "ID", "License"))) {
listPeople.add(createPerson(pdf, role));
}
EDIT: I noticed you're on Java 7, so you could try this instead:
for (String role : pilotRoles) {
for (String attribute : Arrays.asList("Name", "Firstname", "ID", "License")) {
if (StringUtils.isNotBlank(pdf.get(role + attribute))) {
listPeople.add(createPerson(pdf, role));
break;
}
}
}
If you extract this to a method and pass the list of attributes as a parameter, you should also be able to use this for your crew and pilot list.

sort an ArrayList with multiple conditions

say i have an array list MyArrayList<MYObject>
myObject class looks like :
public class myObject
{
String name;
Int age;
String : city;
}
and my dummy data looks like this :
name : martin , age : 20 , city : NY
name : felix , age : 19 , city : LA
name : brian , age : 21 , city : NY
name : brian , age : 19 , city : NY
now i wanna sort myArraylist (which have the above data in it) in this order -
name : felix , lastname : 19 , city : LA
name : brian , lastname : 21 , city : NY
name : martin , lastname : 20 , city : NY
name : brian , lastname : 19 , city : NY
as you can see that the above data is sorted in two ways - firstly by cities then again by age so this is what i wanna do , i wanna sort an arrayList by an order then again i wanna sort in another order by keeping the first order
anyone knows how can i do it ?? please let me know then
if my question is not clear enough then let me know i'll fix it
You can create a Comparator to first compare by city, then by age. Something like this:
Comparator<MyObject> comparator = new Comparator<MyObject>(){
#Override
public int compare(final MyObject o1, final MyObject o2){
if(!o1.getCity().equals(o2.getCity())){
return o1.getCity().compareTo(o2.getCity());
}else{
return o1.getAge().compareTo(o2.getAge());
}
}
};
Collections.sort(myArrayList,comparator);
Edit:
I used the "compareTo" method of the Integer class, which you can't call on an int primitive type. If you use int for the age, you could just write out an if statement for the comparison.
First of all classes should have a descriptive name and the class names should start with an upper case character. So I'll call your class Person
You need to create a custom Comparator to be used by the sort utility.
For a reusable solution you could use the Bean Comparator and the Group Comparator.
The BeanComparator allows you to sort on any property in the object
The GroupComparator allows you to combine multiple Comparator into a single Comparator.
So the basic logic would be:
BeanComparator city = new BeanComparator(Person.class, "getCity");
BeanComparator age = new BeanComparator(Person.class, "getAge");
GroupComparator gc = new GroupComparator(city, age);
Collections.sort(arrayList, gc);
You have two options, which are essentially equivalent:
perform two sorts with a stable sort algorithm: first by age, then by city. A stable sort algorithm is a sorting algorithm that maintains the relative order of two elements A and B if they are equivalent under the current < function. This way, if you first sort by age, when you sort again by city and two elements have the same city, their relative order will be determined by the input order, so they will be sorted by age.
perform a single sort with a compare function that says that A < B whenever A.city != B.city && A.city < B.city or A.city = B.city && A.age > B.age.
Notice that Java's Collections.sort is guaranteed to be stable, so pick whichever strategy better suits your needs.

Inputting strings into arrayLists?

Suppose that I have a code empList and it is an ArrayList. I have 3 Strings, name, boss, and dob holding the data for some employee. I want to write code that creates an Employee from my Strings and then adds it to the empList. I can use the add method of ArrayList to add my employee after I have constructed it, but I'm not too sure how.
This is my Employee class I have written so far:
ArrayList<String> empList = new ArrayList<String>();
class Employee{
Employee(String dob, String name, String boss) //(constructor)
//dob should be mm/dd/yyyy, and boss of length 0 indicates no boss.
int getAge()
String getName()
String getBoss() //returns length 0 string if none
String getDob()
You should change the List declaration to List<Emloyee>:
List<Emloyee> empList = new ArrayList<Emloyee>();
(read more about generics in Java: http://docs.oracle.com/javase/tutorial/java/generics/)
Then you can create a new Employee instance and add it to the list:
Employee employee = new Employee("dob", "John Smith", "His Boss");
empList.add(employee);
By the way: consider changing the type of boss from String to Employee (depending on you use case/meaning).
You might be able to do it in your constructor using
empList.add(this);
However, you'd have to change the type of your ArrayList to Employee, or if you wanted to keep it as a String, then you'd have to create a String in your constructor, and do
String str = "Your string here";
empList.add(str);
I'm also pretty sure that you can't have your ArrayList outside of your class. Java doesn't let you have things outside of classes.
You can add strings to the ArrayList by it's add() method.
You already have the getXXX() methods in your employee class, so you can simply do something along the lines of
String str = "Name: " + emp.getName() + ", Boss: " + emp.getBoss() + ", DoB: " + emp.getDoB();
empList.add(str);
What you probably want is an ArrayList of Employees (ArrayList<Employee>), which would be added in a similar manner, without adding everything to a string.

Categories