SCoder
SCoder

Reputation: 959

Getting filtered records from streams using lambdas in java

I have an entity Employee

class Employee{
          private String name;
          private String addr;
          private String sal;
 }

Now i have list of these employees. I want to filter out those objects which has name = null and set addr = 'A'. I was able to achieve like below :

List<Employee> list2=    list.stream()
            .filter(l ->  l.getName() != null)
            .peek(l -> l.setAddr("A"))
            .collect(Collectors.toList());

Now list2 will have all those employees whose name is not null and then set addr as A for those employees. What i also want to find is those employees which are filtered( name == null) and save them in DB.One way i achieved is like below :

List<Employee> list2=    list.stream()
            .filter(l -> filter(l))
            .peek(l -> l.setAddr("A"))
            .collect(Collectors.toList());

private static boolean filter(Employee l){
    boolean j = l.getName() != null;
    if(!j)
          // save in db
    return j;
}

1) Is this the right way?

2) Can we do this directly in lambda expression instead of writing separate method?

Upvotes: 0

Views: 68

Answers (2)

Holger
Holger

Reputation: 298183

Generally, you should not use side effect in behavioral parameters. See the sections “Stateless behaviors” and “Side-effects” of the package documentation. Also, it’s not recommended to use peek for non-debugging purposes, see “In Java streams is peek really only for debugging?”

There’s not much advantage in trying to squeeze all these different operations into a single Stream pipeline. Consider the clean alternative:

Map<Boolean,List<Employee>> m = list.stream()
    .collect(Collectors.partitioningBy(l -> l.getName() != null));
m.get(false).forEach(l -> {
    // save in db
});
List<Employee> list2 = m.get(true);
list2.forEach(l -> l.setAddr("A"));

Regarding your second question, a lambda expression allows almost everything, a method does. The differences are on the declaration, i.e. you can’t declare additional type parameters nor annotate the return type. Still, you should avoid writing too much code into a lambda expression, as, of course, you can’t create test cases directly calling that code. But that’s a matter of programming style, not a technical limitation.

Upvotes: 4

anacron
anacron

Reputation: 6721

If you are okay in using peek for implementing your logic (though it is not recommended unless for learning), you can do the following:

List<Employee> list2=    list.stream()
        .peek(l -> { // add this peek to do persistence
              if(l.getName()==null){
                  persistInDB(l);
              }
        }).filter(l ->  l.getName() != null)
        .peek(l -> l.setAddr("A"))
        .collect(Collectors.toList());

You can also do something like this:

    List<Employee> list2 =    list.stream()
              .filter(l->{
                  boolean condition = l.getName()!=null;
                  if(condition){
                      l.setAddr("A");
                  } else {
                      persistInDB(l);
                  }
                  return condition;
              })
              .collect(Collectors.toList());

Hope this helps!

Upvotes: 0

Related Questions