2

I am doing simple test.

@Test
    public void whenFilterEmployees_thenGetFilteredEmployees(){
        Integer[] empIds = {1,2,3};
        List<Optional<Employee>> employees = Stream.of(empIds)
                .map(employeeRepository::findById)
                .collect(Collectors.toList());

        List<Employee> employeeList = employees
                .stream().filter(Optional::isPresent)
                .map(Optional::get)
                .filter(e->e !=null)
                .filter(e->e.getSalary()>200000)
                .collect(Collectors.toList());

        assertEquals(Arrays.asList(arrayOfEmps[2]), employeeList);


    }

and my employee table contains data:

1   Jeff Bezos  100000
2   Bill Gates  200000
3   Mark Zuckerberg 300000

the current test runs successfully.

as you can see i have prepared two list of employees i.e employees and employeeList

i did so because findById method returns Optional. how can i use the streams api so that i can get list of employees simply as

List<Employee> employeeList= ....
3
  • There is no reason to split both streams. Just use one, request the DB, filter if present, apply other filters, then collect to list. Commented Oct 30, 2018 at 10:15
  • Possible duplicate of Using Java 8's Optional with Stream::flatMap Commented Oct 30, 2018 at 10:49
  • @LuisG. Not a duplicate as the question is not asking about that. Commented Oct 30, 2018 at 10:53

2 Answers 2

6

Just merge the two stream pipelines i.e.

List<Employee> employees = Stream.of(empIds)
                                 .map(employeeRepository::findById)
                                 .filter(Optional::isPresent)
                                 .map(Optional::get)
                               //.filter(e->e !=null) not needed as it's redundant
                                 .filter(e->e.getSalary()>200000)
                                 .collect(Collectors.toList());
Sign up to request clarification or add additional context in comments.

3 Comments

does it work ? because i get non-static method cannot be referenced from static context on .filter(Optional::isPresent)
@sagarlimbu on my phone atm but I don’t see a reason why it shouldn’t compile. Probably a type inference issue... what IDE are you using?
sorry i didn't see your answer properly. i actually used filter(Optional::get) instead of .map(Optional::get).
4

We can write the code shorter using Optional.stream (requires Java 9+):

List<Employee> employees = Stream.of(empIds)
        .flatMap(id -> employeeRepository.findById(id).stream())
        .filter(e -> e.getSalary() > 200000)
        .collect(Collectors.toList());

According to the JavaDoc Optional.stream

returns a sequential Stream containing only that value, otherwise returns an empty Stream.

Thus we can go on with the filter operation at once.

7 Comments

@Holger Added this to my answer. Thx.
Just read your comment about "method reference overuse" :). As I wrote how to get the code shorter, it's only consistent to follow your suggestion. Updated my answer.
Well, I wouldn’t consider two method references “overuse”. And it’s easier to overlook when map and flatMap steps can be merged. It’s a different beast with four subsequent map steps…
Wouldn't you still need a check for null, since op checks for null?
Correct. The JavaDoc for Optional.isPresent says: "If a value is present, returns true, otherwise false." So if the Optional is empty, the filter will not be passed. But if it's passed, then it's safe to call Optional.get and the value returned is not null.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.