0

I am trying to stream a list of strings. I know we can do it like below:

list.stream().filter(i -> !Stringutils.isempty(service.someMethod(i))).map(i -> service.someMethod(i)).findfirst().get();

The problem is I need to call the service.someMethod twice.

Any suggestions here to avoid the service.someMethod calling it twice once in filter and another one for mapping?

ChristianYami
  • 586
  • 1
  • 9
  • 17
JingJong
  • 207
  • 1
  • 3
  • 14

2 Answers2

3

You should reverse map and filter as such:

list.stream() 
    .map(service::someMethod)
    .filter(s -> !Stringutils.isEmpty(s)) // or if it exists, StringUtils::isNotEmpty
    .findFirst()
    .get()
Unmitigated
  • 76,500
  • 11
  • 62
  • 80
NoDataFound
  • 11,381
  • 33
  • 59
  • 3
    Or, if `someMethod` is never returning `null`, just `s -> !s.isEmpty()`. In fact, even if the method can return `null`, I’d rather use `s -> s !=null && !s.isEmpty()`, instead of adding a 3rd party library dependency that makes it unrecognizable if `null` handling is wanted or not. – Holger Jul 02 '20 at 07:43
  • I'm fine with your comment, but I was answering the question which used `Stringutils` (notice the lowercase `u`:)). I would personally use a method reference rather than a lambda, especially for common String related code, and if present, use common-lang3/4. – NoDataFound Jul 02 '20 at 19:39
1

I love working with java8 streams, hope you do too.

it seems that you want to map list with someMethod and then filter not-empty values, so just do this! the only thing you should do is to change the order of map and filter. after changing orders, someMethod will only be called once, because we map them once and filter the mapped values.

new code will be like this:

 String answer = list
       .stream()
       .map(a -> service.someMethod(a))
       .filter(a -> !a.isEmpty())
       .findFirst()
       .get();

and better, you can replace lambda with method reference

     .map(service::someMethod)
     // same as .map(a -> service.someMethod(a))

(sorry for my english)

  • Thanks for the detailed explanation. – JingJong Jul 01 '20 at 19:44
  • Just to add a side note, make sure that to use ```isBlank()``` method if you use JDK 11 https://stackoverflow.com/questions/51299126/difference-between-isempty-and-isblank-method-in-java-11?noredirect=1&lq=1 – parrotjack Jul 01 '20 at 23:07
  • 2
    @parrotjack using `isBlank()` only makes sense, if the different semantic of `isBlank()` is actually intended. There is no indication here, that `isBlank()` is intended. – Holger Jul 02 '20 at 07:46
  • @Holger makes sense, but for safer side i just mentioned. No harm. – parrotjack Jul 02 '20 at 10:17