How to do this using collections/ stream api - java

I have this Requirement :
Construct each Doctor with their respective Appointments and return a doctorList. Input is Appointment List for whole Hospital.
What I have is the followings:
Two classes given with the following variables.
Class Appointment{
String doctorName;
DateTime startTime;
DateTime endTime;
String speciality;
//Getters-Setters
}
Another Class :
Class Doctor{
String name;
String speciality;
List <Appointment> appointments;
//Getters-Setters
}
Requirement is :
Construct each Doctor with their respective Appointments and return a doctorList.
Input is Appointment List for whole Hospital.
Can some body tell what should be my approach?

I hope this will help you. Use Map to maintain the appointments of each doctor. In the below code you can get the appointment details using the doctor's name.
`//appointments - input list
Map<String, List<Appointment>> map = new HashMap<>();
for(Appointment app : appointments) {
if(!map.containsKey(app.getDoctorName())) {
List<Appointment> li = new ArrayList<>();
li.add(app);
map.put(app.getDoctorName(),li);
} else {
map.get(app.getDoctorName()).add(app);
}
}`

You can use HashMap.
HashMap<Doctor, ArrayList> doctorList = new HashMap<>();
Might not be a good idea in your case mainly because I do not understand what you are trying to achieve.

If you need match doctors with Appointment by both Speciality and Name, then:
Map<String, List<Appointment>> map = appointmentList
.stream()
.collect(Collectors.groupingBy(e -> e.getDoctorName() + e.getSpeciality()));
List<Doctor> doctors = new ArrayList<>();
for (String doctorNameAndSpeciality : map.keySet()) {
List<Appointment> appointments = map.get(doctorNameAndSpeciality);
if (!appointments.isEmpty()) {
Doctor doctor = new Doctor();
Appointment appointment = appointments.get(0);
doctor.setName(appointment.getDoctorName());
doctor.setSpeciality(appointment.getSpeciality());
doctor.addAllAppointments(appointments);
}
}
return doctors;
if you need use only 'name', then just remove 'speciality'

Related

Create ArrayList from Postgresql query

I have following class:
public class Person {
private String firstName;
private String lastName;
private List<String> habits;
}
I have Postgres query which returns me following result using inner join from 2 tables
name | lastname| habits
--------------------------------------
John | Smith | ["walking", "eating"]
I am trying to write RowMapper as following:
private final RowMapper<Person> rowMapper = (rs, rowNum) -> {
String firstName = rs.getString("name");
String lastName = rs.getString("lastName");
}
I am not sure how to create List habits from "habits column in my result table"
Please advise
Thanks
Found an answer
The code below is working fine
String[] habits;
try {
habits = objectMapper.readValue(rs.getString("habits"), String[].class);
} catch (JsonProcessingException e) {
throw new RuntimeException(e);
}
List<String> habitsList = Arrays.stream(habits).toList();
I have tried it and working fine. You can try the below code what I have understand from your description.
String firstName = rs.getString("name");
String lastName = rs.getString("lastName");
List<String> list = rs.getObject("habits");
if you get compilation error, it will work definitly
List stringList = new ArrayList;
List objectList = stringList;// this does compile only if List where subtypes of List
objectList.add(new Object());
String s = stringList.get(0);
it should work.
Let me know if you facing still issue

JDBC resultset into java POJO with list member

I have two query and resultsets, in the below code I want to showcase that for a particular userGroupCode I have certain userPreference and employee associated with it. I have written the code below code to display the userGroupCode object:
String query1= "SELECT ug.userGroupCode, ug.userGroupDesc, up.userPreference"
+ "FROM dbo.UserGroup_link ug INNER JOIN dbo.UserPreference up ON ug.userGroupCode = up.userGroupCode";
userGroupCode
userGroupDesc
userPreference
A100
Finance
Mumbai
A100
Finance
Bangalore
A200
Supply Chain
Chennai
A201
Marketing
Delhi
A201
Marketing
Kolkata
A300
Health
Indore
String query2= "SELECT ug.userGroupCode, ug.userGroupDesc, emp.employee_id,emp.name,emp.role"
+ "FROM dbo.UserGroup ug INNER JOIN dbo.employee emp ON ug.userGroupCode = emp.userGroupCode";
userGroupCode
userGroupDesc
employee_id
name
role
A100
Finance
101
Foo1
Developer
A100
Finance
101
Foo1
Team Lead
A200
Supply Chain
091
Test1
Manager
A201
Marketing
591
User1
Analyst
A201
Marketing
1001
Boo1
Scrum Master
A300
Health
1001
Boo1
Developer
I have class UserGroupMapping like:
public class UserGroupMapping {
private String userGroupCode;
private String userGroupCode;
private List<String> userPreference;
private List<Employee> emp;
//getter and setter
}
Another class for Employee is:
public class Employee {
private String employee_id;
private String name;
private List<String> role;
//getter and setter
}
In my stored procedure class I am calling these queries with the help of jdbcTemplate.query();
String userCode = null;
List<String> userPreferenceList = new ArrayList<>();
List<UserGroupMapping> userGroupMappingList = new ArrayList<>();
List<UserGroupMapping> userGroupMappingList1 = new ArrayList<>();
UserGroupMapping userGroupMapping = new UserGroupMapping();
List<Employee> employeeList = new ArrayList<>();
Employee emp = new Employee();
UserGroupMapping userGroupMapping1 = new UserGroupMapping();
jdbcTemplate.query(query1, (rs)->{
String user_group_code = rs.getString("userGroupCode");
String user_group_desc = rs.getString("userGroupDesc");
String user_preference = rs.getString("userPreference");
if(userCode == null){
userGroupMapping.setUserGroupCode(user_group_code);
userGroupMapping.setUserGroupDesc(user_group_desc);
userPreferenceList.add(userPreference);
userCode = user_group_code;
} else if (userCode.equals(user_group_code)) {
userPreferenceList.add(userPreference);
} else {
userGroupMapping.setUserPreference(userPreferenceList);
userGroupMappingList.add(userGroupMapping);
userPreferenceList = new ArrayList<>();
userGroupMapping = new userGroupMapping();
userGroupMapping.setUserGroupCode(user_group_code);
userGroupMapping.setUserGroupDesc(user_group_desc);
userPreferenceList.add(userPreference);
userCode = user_group_code;
}});
userCode = null;
userGroupMapping.setUserPreference(userPreferenceList);
userGroupMappingList.add(userGroupMapping);
jdbcTemplate.query(query2, (rs)->{
String user_group_code = rs.getString("userGroupCode");
String user_group_desc = rs.getString("userGroupDesc");
String emp_id = rs.getString("employee_id");
String name = rs.getString("name");
if(userCode == null){
userGroupMapping1.setUserGroupCode(user_group_code);
userGroupMapping1.setUserGroupDesc(user_group_desc);
emp.setId(employeeId);
emp.setName(name);
employeeList.add(emp);
userCode = user_group_code;
} else if (userCode.equals(user_group_code)) {
Employee emp = new Employee();
emp.setId(employeeId);
emp.setName(name);
employeeList.add(emp);
} else {
userGroupMapping1.setEmployee(employeeList);
userGroupMappingList1.add(userGroupMapping1);
employeeList = new ArrayList<>();
userGroupMapping1 = new userGroupMapping();
Employee emp = new Employee();
userGroupMapping1.setUserGroupCode(user_group_code);
userGroupMapping1.setUserGroupDesc(user_group_desc);
emp.setId(employeeId);
emp.setName(name);
employeeList.add(emp);
userCode = user_group_code;
}});
userGroupMapping1.setEmployee(employeeList);
userGroupMappingList1.add(userGroupMapping1);
List<UserGroupMapping> ugList = Stream.concat(userGroupMappingList.stream, userGroupMappingList1.stream).distinct().collect(Collectors.toList())
return ugList;
The problem is that I want my output to be like :
[
{
"userGroupCode" : "A100",
"userGroupDesc" : "Finance",
"userPreference": ["Mumbai","Bangalore"],
"Employee" : [
"employee_id" : "101",
"name" : "Foo1",
"role" : ["Developer","Team Lead"]
]
}
]
After merging the two list I am getting the below output:
[
{
"userGroupCode" : "A100",
"userGroupDesc" : "Finance",
"userPreference": ["Mumbai","Bangalore"],
"Employee" : []
},
{
"userGroupCode" : "A100",
"userGroupDesc" : "Finance",
"userPreference": [],
"Employee" : [
"employee_id" : "101",
"name" : "Foo1",
"role" : []
]
}
]
Could anyone please help me with few things:
How could I embed the role into the Employee object.
How can I merge the table based on userGroupCode and userGroupDesc.
I am feeling the code is not that performance optimised, How could I optimised this code.
Thank you in advance.
Ola,
You can group by using Map taking id as key and value as object ( to be aggregated into) . For example:
if(map.containes(key))
{
get object from map and do Ops.
}
else
{
1. Create new object
2. Do set Ops on Object
3. Add to map.
}
You basically have 2 solutions,
Write a query that returns all results with joins and do filtering in java, quite easy to achieve with 2 maps (one for the UserGroup the other for the Employee.
Write a query and aggregate the duplicates using list in the query itself.
SELECT ug.userGroupCode, ug.userGroupDesc, up.userPreference, emp.employee_id,emp.name,emp.role
FROM dbo.UserGroup_link ug
INNER JOIN dbo.UserPreference up ON ug.userGroupCode = up.userGroupCode
INNER JOIN dbo.employee emp ON ug.userGroupCode = emp.userGroupCode
Then use a RowCallbackHandler to achieve what you want (instead of a ResultSetExtractor.
Map<String, UserGroup> userGroups = new HashMap<>;
Map<Integer, Employee> employees = new HashMap<>;
jdbc.query(query, (rs) -> {
String userGroupCode = rs.getString("userGroupCode");
String emp_id = rs.getString("employee_id");
UserGroupMapping ugm userGroups.computeIfAbsent(userGroupCode, {
UserGroupMapping ugm1 = new UserGroupMapping();
ugm1.setUserGroupCode(userGroupCode);
ugm1.setUserGroupDesc(rs.getString("userGroupDesc");
ugm1.setUserPreference(new ArrayList<>());
ugm1.getEmployee(new ArrayList<>());
return ugm1;
});
ugm.getUserPreference().add(rs.getString("userPreference"));
Employee emp = employees.computeIfAbsent(emp_id, {
Employee emp1 = new Employee();
emp1.setName(rs.getString("name"));
emp1.setRole(new ArrayList<>());
ugm.getEmployee().add(emp);
return emp1;
});
emp.getRole().add(rs.getString("role"));
});
return userGroups.values();
The above code will get all UserGroupMapping objects from the result including all the Employee instances. The temporary maps are needed to determine if record has already been shown.
Another solution would be to use list in your query and some GROUP BY statement to let the query do part of the aggregation. That way you could make it a bit easier to create an Employee.

Adding element to List from csv file like Arraylist.add

Here is my code:
public static Map<String, List<Customer>> readCustomerData() throws IOException {
Map<String, List<Customer>> customers =
Files.lines(Paths.get("customer.csv"))
.map(line -> line.split("\\s*,\\s*"))
.map(field -> new Customer(
Integer.parseInt(field[0]), field[1],
Integer.parseInt(field[2]), field[3]))
.collect(Collectors
.groupingBy(Customer::getName));
System.out.println (customers);
return customers;
}
I notice that this code read my data in the csv file into one element like this:
(Ali = ["1 Ali 1201345673 Normal"] , Siti = ["2 Siti 1307891435 Normal"])
But in my thinking , I would like to read the data like the array list such as for Ali: 1 is an element , Ali is an element , 1201345673 is an element and Normal is another element in the list in the Map customer. How can I modify my code to do such a thing?
This is my Customer class just in case:
public class Customer {
private int customerNo;
private String name;
private int phoneNo;
private String status;
public Customer () {}
public Customer (int customerNo, String name, int phoneNo, String status){
this.customerNo = customerNo;
this.name = name;
this.phoneNo = phoneNo;
this.status = status;
}
public String getName(){
return name;
}
public String toString(){
return customerNo + " " + name + " " + phoneNo + " " + status;
}
Here is my csv file:
1,Ali,1201345673,Normal
2,Siti,1307891435,Normal
Thank you for your attention.
Assuming that the customer names are unique, there's no need to return a Map<String, List<Customer>>, since each List will contain a single Customer.
You can change your code to:
Map<String, Customer> customers =
Files.lines(Paths.get("customer.csv"))
.map(line -> line.split("\\s*,\\s*"))
.map(field -> new Customer(
Integer.parseInt(field[0]), field[1],
Integer.parseInt(field[2]), field[3]))
.collect(Collectors.toMap(Customer::getName, Function.identity()));
And if the names are not unique, you can index the customers by the customer IDs.
As for I would like to read the data like the array list such as for Ali: 1 is an element , Ali is an element , 1201345673 is an element and Normal is another element in the list in the Map customer - this doesn't make sense to me. You already create a Customer object from each line of your input, which is much more useful and type safe compared to a List of properties.

Aggregate HQL result to list

I want to group some sql data using criteria. Lets start with entity which looks mostly like this:
class CityEntity {
private String name;
private Date lastVisited;
}
What I want to do is to find all cities and return result in a tranformer:
class CityTransformer {
private String name;
private List<Date> lastVisited;
}
So as you can see sql result should group by name and put dates to a list.
I want to do it using criteria so it will look almost like this:
Criteria criteria = session.createCriteria(CityEntity.class, "ce");
criteria.setProjection(Projections.projectionList().add(Projections.groupProperty("name"), "name"));
criteria.setResultTransformer(Transformers.aliasToBean(CityTransformer.class));
List<CityTransformer> cities = criteria.list();
The problem is that I don't know how to aggregate dates (lastVisited) to list. Any help?
For example the input will look like this (name, lastVisited):
[Los Angeles, 10-11-2014],
[Los Angeles, 11-12-2011],
[LosAngeles, 10-01-2011],
[Berlin, 01-10-2011]
and output should look like this
[LosAngeles, list[10-11-2014, 11-12-2011, 10-01-2011]],
[Berlin, list[01-10-2011]]
You don't need SQL grouping for that. You can group it in Java:
Criteria criteria = session.createCriteria(CityEntity.class, "ce");
criteria.setProjection(
Projections.projectionList()
.add( Projections.property("ce.name"), "ceName" )
.add( Projections.property("ce.lastVisited"), "ceLastVisited" )
);
List<Object[]> citiesAndDates = (List<Object[]>) criteria.list();
Map<String, CityTransformer> cityTransformerMap = new HashMap<String, CityTransformer>();
for(Object[] citiesAndDate : citiesAndDates) {
String city = (String) citiesAndDate[0];
Date date = (Date) citiesAndDate[1];
CityTransformer cityTransformer = cityTransformerMap.get(city);
if(cityTransformer == null) {
cityTransformer = new CityTransformer();
cityTransformerMap.put(city, cityTransformer);
}
cityTransformer.getLastVisited().add(date);
}
return cityTransformerMap;

Filtering an arraylist using a method

I am trying to return a list of doctors who have a patient based on a date given by the user. But each time I run the method, it returns the list of all doctors instead of being filtered.
Code on Main
public void printDoctorsWithPatientsOnDate() throws ParseException
{
ArrayList<String> docs = new ArrayList();
System.out.print("Enter the date(mm-dd-yyyy): ");
Date dt = new SimpleDateFormat("MM-dd-yyyy").parse(sc.nextLine());
docs = app.getDoctorsWithPatientsOnDate(dt);
for(String i : docs)
{
System.out.println(i);
}
}
Method for filtering
public ArrayList<String> getDoctorsWithPatientsOnDate(Date date)
{
ArrayList<String> doctors = new ArrayList();
for(Patient i : patientList)
{
if(i.searchDatesForDoc(date) == true);
{
doctors.add(i.getDoctorName());
}
}
return doctors;
}
Method for searching the dates of a patient
public boolean searchDatesForDoc(Date date){
for(Date i : datesOfVisit)
{
if(i.equals(date))
{
return true;
}
}
return false;
}
I have initialized 2 patients namely patient1 and patient 2. patient1's doctor is named dr.lee and patient 2's doctor is named dr.james. first, i enter the following information for patient1 and i left patient2 with nothing(for now).
Enter the Patient's name: patient1
Enter the assessment: alz
Enter the date of Visit(mm-dd-yyyy): 10-02-2010
and the problem comes when I get the list of doctors. Even though the date is wrong, it keeps on printing the every doctor on the list.
Enter the date(mm-dd-yyyy): 11-20-2012
dr.lim
dr.james
For some unknown reason (to me anyway), the accepted answer that I gave was deleted by a moderator.
The problem has been resolved. The problem was that he had an extra semicolon after the if statement.
I don't have all the code to reproduce, but I would focus on the searchDatesForDoc method first. Try this:
public ArrayList<String> getDoctorsWithPatientsOnDate(Date date)
{
ArrayList<String> doctors = new ArrayList();
for(Patient i : patientList)
{
System.out.println("Current patient is: " + i.getPatientName());
if(i.searchDatesForDoc(date) == true);
{
doctors.add(i.getDoctorName());
}
}
return doctors;
}
public boolean searchDatesForDoc(Date date){
for(Date i : datesOfVisit)
{
if(i.equals(date))
{
System.out.println("\tVisited on day: " + i);
return true;
}
}
return false;
}
When you run with those two lines added, it will print the patient name followed with the days that the patient visited. First thing to check is whether or not the patient actually did visit on those dates listed. If not, then your problem is there. This would be a lot easier to debug with a debugger to trace through each step of your code.

Categories

Resources