Home > Mobile >  Perform multiple unrelated operations in map function
Perform multiple unrelated operations in map function

Time:01-05

I have a list 'inputList' where I want to apply a method on each element, and add the result in another list 'outputList' and in another map 'outputMap'. Below are the 2 Operations

getEmployeeDetails(String employeeId) 

and

getEmployeeSkills( String employeeId) 

need to be performed for all elements of inputList.

When I use foreach as below , in this case I can do multiple operations

inputList.stream()
        .foreach ( elem -> 
              {
                outputList.add( employeeRepository.getEmployeeDetails(elem));       
                outputMap.put( elem, employeeRepository.getEmployeeSkills(elem);                                                                                       });

However, if I use recommended way of using map() function, then I am unable to perform both operations and able to perform only getEmployeeDetails() functions.

outputList = inputList.stream()
        .map(elem -> employeeRepository.getEmployeeDetails(elem))
        .collect(Collectors.toList()); 

Is it possible to do something like this?

outputList = inputList.stream()
        .map(elem -> {
                        employeeRepository.getEmployeeDetails(elem));
                        outputMap.put( elem, employeeRepository.getEmployeeSkills(elem);    
        .collect(Collectors.toList()).collect(Collectors.toMap()); 

One more clarification is it is advisable to make database calls from stream? If not, what would be the better approach?

 inputList .stream()
        .foreach ( elem -> 
              {
                outputList.add( employeeRepository.getEmployeeDetails(elem));       
                outputMap.put( elem, employeeRepository.getEmployeeSkills(elem);     
                                                                                     });

CodePudding user response:

You cannot perform a map operation and collect two results into two different collections, so the foreach is already a good approach.

If you are concerned about performance you might be better off with a plain old for loop.

If your original list is the result of a database query probably you better do the join operation in a database query instead of performing an extra query for each entry in the list - but how to perform that is topic for another question (and needs other details to be included in the question anyways).

CodePudding user response:

Joining should probably be done in your repository, so you can just fetch an employee with details and skills.

To answer your specific question how to do it with streams and map you can do something like this, you will still need an Employee wrapper class though. Here I assumed Employee would have a constructor that would take the id.

input.stream()
        .map(Employee::new)
        .map(employee -> {
            employee.setSkills(getEmployeeSkills(employee.getId()));
            return employee;
        })
        .map(employee -> {
            employee.setDetails(getEmployeeDetails(employee.getId()));
            return employee;
        })
        .collect(Collectors.toList());

CodePudding user response:

Since you are not really collecting the outputMap using the stream functionality, you can use map effectively for this purpose.

outputMap = new HashMap<String, Skills>();
outputList = inputList.stream()
    .map(elem -> {
       outputMap.put(elem, employeeRepository.getEmployeeSkills(elem));    
       return employeeRepository.getEmployeeDetails(elem));
    })
    .collect(Collectors.toList());

It is not beautiful to have a side effect in the stream like that, but it is simple to read, and I don't think you will get anything to run much faster.

  • Related