简体   繁体   中英

How to organize java 8 code with Functional interfaces

I have recently started reading about java 8 features and i am confused with what seems like a very basic thing. How to organize code in 'Functional style' ? Whatever i do, it looks very object oriented to me.

Best to explain what i ask with an example.

    @FunctionalInterface
    public interface SubstringOperator {

        String splitAtLastOccurence(String plainText, String delimiter);

    }

Let's say that in certain class i always need exactly one specific implementation of the SubstringOperator interface. I could provide implementation in the constructor like below:

public class SomeClass {

    private SubstringOperator substringOperator;

    public SomeClass() {

        substringOperator = (s, d) -> { return s.substring(s.lastIndexOf(d)+1);};
    }
}

I could now use this implementation in any method within SomeClass like this:

 //...
String valueAfterSplit = substringOperator.splitAtLastOccurence(plainText, "=");

If i now wish to add another class which reuses that specific SubstringOperator implementation, should i create another class which exposes the implementation via getters?

Am i missing something obvious, or:

  • functions must be contained in classes in order to reuse them ?
  • How is that any different than object oriented paradigm ?

Put aside Stream API and other thingies, i would like to get basic understanding about code organization in java 8 for Functional style programming.

Usually it's better to reuse existing functional interfaces instead of creating new ones. In your case the BinaryOperator<String> is what you need. And it's better to name the variables by their meaning, not by their type. Thus you may have:

public class SomeClass {
    private BinaryOperator<String> splitAtLastOccurence = 
        (s, d) -> s.substring(s.lastIndexOf(d)+1);
}

Note that you can simplify single-statement lambda removing the return keyword and curly brackets. It can be applied like this:

String valueAfterSplit = splitAtLastOccurence.apply(plainText, "=");

Usually if your class uses the same function always, you don't need to store it in the variable. Use plain old method instead:

protected static String splitAtLastOccurence(String s, String d) {
    return s.substring(s.lastIndexOf(d)+1);
}

And just call it:

String valueAfterSplit = splitAtLastOccurence(plainText, "=");

Functions are good when another class or method is parameterized by function, so it can be used with different functions. For example, you are writing some generic code which can process list of strings with additional other string:

void processList(List<String> list, String other, BinaryOperator<String> op) {
    for(int i=0; i<list.size(); i++) {
        list.set(i, op.apply(list.get(i), other));
    }
}

Or more in java-8 style:

void processList(List<String> list, String other, BinaryOperator<String> op) {
    list.replaceAll(s -> op.apply(s, other));
}

In this way you can use this method with different functions. If you already have splitAtLastOccurence static method defined as above, you can reuse it using a method reference:

processList(myList, "=", MyClass::splitAtLastOccurence);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM