我最近开始阅读有关java 8功能的内容,我对这似乎是一件非常基本的事情感到困惑。如何在功能样式中组织代码' ? 无论我做什么,它看起来都非常面向我。
最好用一个例子来解释我的问题。
@FunctionalInterface
public interface SubstringOperator {
String splitAtLastOccurence(String plainText, String delimiter);
}
让我们说在某些class
我总是需要SubstringOperator
接口的一个特定实现。我可以在构造函数中提供如下所示的实现:
public class SomeClass {
private SubstringOperator substringOperator;
public SomeClass() {
substringOperator = (s, d) -> { return s.substring(s.lastIndexOf(d)+1);};
}
}
我现在可以在SomeClass
中的任何方法中使用此实现,如下所示:
//...
String valueAfterSplit = substringOperator.splitAtLastOccurence(plainText, "=");
如果我现在希望添加另一个重用该特定SubstringOperator
实现的类,我应该创建另一个通过getter公开实现的类吗?
我错过了一些明显的东西,或者:
抛开Stream API和其他东西,我希望对java 8中用于功能样式编程的代码组织有基本的了解。
答案 0 :(得分:4)
通常最好重用现有的功能接口而不是创建新接口。在您的情况下,BinaryOperator<String>
就是您所需要的。最好根据变量的含义命名变量,而不是按类型命名变量。因此,你可能有:
public class SomeClass {
private BinaryOperator<String> splitAtLastOccurence =
(s, d) -> s.substring(s.lastIndexOf(d)+1);
}
请注意,您可以简化单语句lambda,删除return
关键字和大括号。它可以像这样应用:
String valueAfterSplit = splitAtLastOccurence.apply(plainText, "=");
通常,如果您的类始终使用相同的函数,则无需将其存储在变量中。改为使用普通旧方法:
protected static String splitAtLastOccurence(String s, String d) {
return s.substring(s.lastIndexOf(d)+1);
}
请致电:
String valueAfterSplit = splitAtLastOccurence(plainText, "=");
当按功能参数化另一个类或方法时,函数很好,因此它可以用于不同的函数。例如,您正在编写一些通用代码,可以处理带有附加other
字符串的字符串列表:
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));
}
}
或者更多java-8风格:
void processList(List<String> list, String other, BinaryOperator<String> op) {
list.replaceAll(s -> op.apply(s, other));
}
通过这种方式,您可以将此方法用于不同的功能。如果您已经如上所述定义了splitAtLastOccurence
静态方法,则可以使用方法引用重用它:
processList(myList, "=", MyClass::splitAtLastOccurence);