Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Convert lambdas to method references

Can somebody help me convert the following code to use method references? I'm trying to wrap my head around this new syntax but I quickly get lost when it gets more complex than a single variable getting mapped to a single method call:

getWorkspaces().stream().forEach((ws) -> {
            DataStoreInfo defaultDataStore = getDefaultDataStore(ws);
            if (defaultDataStore != null) {
                other.setDefaultDataStore(ws, defaultDataStore);
            }
        });

I started with this, but it doesn't work :)

getWorkspaces().stream()
               .map(this::getDefaultDataStore)
               .filter(Objects::nonNull)
               .map(other::setDefaultDataStore);

Edit: By "it doesn't work", I mean the IDE complains on the last line under "setDefaultDataStore" that it cannot resolve the method. I wish I could start with something that works, but I don't know how to get there. I'm very confused on how to use method references to call a method that takes 2 parameters and how that gets mapped. I've converted some code that looks like this:

 getMaps().stream().forEach((m) -> {
            other.add(m);
        });

to this:

getMaps().forEach(other::add);

But I get lost when it gets more complex. I was hoping there was an obvious solution on how to write same code with method references.

like image 719
Bal Avatar asked Oct 12 '16 12:10

Bal


2 Answers

You can read a lot of useful information here about method references https://docs.oracle.com/javase/tutorial/java/javaOO/methodreferences.html

If your lambda does nothing but calls existed method, you can replace it with method reference. So if you are comfortable with lambdas you will cope with method references easily.

There are 4 kinds of them

  1. Reference to a static method - ContainingClass::staticMethodName
  2. Reference to an instance method of a particular object - containingObject::instanceMethodName
  3. Reference to an instance method of an arbitrary object of a particular type - ContainingType::methodName
  4. Reference to a constructor - ClassName::new

Returning to your question: .map(other::setDefaultDataStore);

You shouldn't use map function to perform some side operations over stream members, it is used for transforming stream into another. User foreach instead

getWorkspaces().stream()
               .map(this::getDefaultDataStore)
               .filter(Objects::nonNull)
               .foreach(other::setDefaultDataStore);
like image 181
cringineer Avatar answered Oct 13 '22 01:10

cringineer


You can convert your code to the lambda version like this but its not clean as expected.

words.stream().map(ws -> new SimpleImmutableEntry<>(ws, getDefaultDataStore(ws)))
              .filter(e -> e.getValue() != null)
              .forEach(e -> setDefaultDataStore(e.getKey(), e.getValue()));

Note : e is the short for entry .

like image 34
Ömer Erden Avatar answered Oct 12 '22 23:10

Ömer Erden