我正在探索Java 8的功能,并遇到了"功能接口".
根据我的理解,这些接口可以有一些默认的实现方法:
@FunctionalInterface
public interface ComplexFunctionalInterface extends SimpleFuncInterface
{
default public void doSomeWork()
{
System.out.println("Doing some work in interface impl...");
}
default public void doSomeOtherWork()
{
System.out.println("Doing some other work in interface impl...");
}
}
Run Code Online (Sandbox Code Playgroud)
但我怀疑的是,这是抽象类的用途.
为什么要介绍的功能接口.
如果我编写了ToIntFunction接口,我想在接口中编码它只是一个返回原始int的函数,如下所示:
@FunctionalInterface
public interface ToIntFunction<T> extends Function<T, Integer> {
int applyAsInt(T value);
@Override
default Integer apply(T value) {
return Integer.valueOf(applyAsInt(value));
}
}
Run Code Online (Sandbox Code Playgroud)
我想知道,有没有令人信服的理由让Java 8 API设计人员选择将原始备选方案与Function完全分开?是否有一些证据表明他们认为这样做并决定反对呢?我想类似的问题至少包括其他一些"特殊"功能接口,如Consumer(可能是Function <T,Void>)和Supplier(Function <Void,T>).
我没有深入和彻底地考虑过这个问题的所有后果,所以我可能会遗漏一些东西.
如果ToIntFunction(和其他原始泛型函数接口)与Function有这种关系,它将允许一个人在预期使用Function参数的位置使用它(想到的是与其他函数的组合,例如调用myFunction.compose(myIntFunction))或者当在如上所述的这种自动(非)装箱实现就足够时避免在API中编写几个专用函数.
这与这个问题非常相似:为什么Java 8的Predicate <T>不扩展Function <T,Boolean>但我已经意识到答案可能因语义原因而不同.因此,我正在重新设计这个函数的简单原始替代方案的问题,其中不存在任何语义,只是原始与包装类型,甚至消除了空包装对象的可能性.
我希望对我定义的函数列表进行惰性评估,如下所示;
Optional<Output> output = Stream.<Function<Input, Optional<Output>>> of(
classA::eval, classB::eval, classC::eval)
.map(f -> f.apply(input))
.filter(Optional::isPresent)
.map(Optional::get)
.findFirst();
Run Code Online (Sandbox Code Playgroud)
如您所见,每个类(a,b和c)都Optional<Output> eval(Input in)定义了一个方法.如果我尝试做
Stream.of(...)....
Run Code Online (Sandbox Code Playgroud)
它忽略了显式类型
T不是功能界面
编译错误.不接受T泛型类型的功能接口类型.of(T... values)
有没有更快捷的方法来创建这些功能的流?我讨厌明确定义of方法Function及其输入输出类型.它不会以更通用的方式工作吗?
这个问题源于以下问题的主题;
Lambda表达式和通用方法
在isReadyToDeliver方法中,如果订单中的所有产品都可用(ProductState.AVAILABLE)并且订单状态已准备好发送(OrderState.READY_TO_SEND),则方法必须返回true.我写了两部分,但我无法将它们组合在一起,
我写了,return orderState.andThen(productState)但得到这个错误:
andThen(Function<? super Boolean,? extends V>)类型中的方法Function<Order,Boolean>不适用于参数(Function<Order,Boolean>)
public class OrderFunctions {
public Function<Order, Boolean> isReadyToDeliver() {
Function<Order, Boolean> orderState = o -> o.getState() == OrderState.READY_TO_SEND;
Function<Order, Boolean> productState =
o -> o.getProducts()
.stream()
.map(Product -> Product.getState())
.allMatch(Product -> Product == ProductState.AVAILABLE);
return ????? ;
//return orderState.andThen(productState);
//error: The method andThen(Function<? super Boolean,? extends V>) in the type Function<Order,Boolean> is not applicable for the arguments (Function<Order,Boolean>) …Run Code Online (Sandbox Code Playgroud) java lambda functional-programming java-8 functional-interface
我很久以前就遇到过一个比我更好的竞争性答案,它使用了一个非常新的方法参考我作为lambda的替代品.
Stream.generate(new AtomicInteger(1)::getAndIncrement)...
Run Code Online (Sandbox Code Playgroud)
我查看了有关Method引用的Oracle规范,并定义了4种类型:
ContainingClass::staticMethodNamecontainingObject::instanceMethodNameContainingType::methodNameClassName::new我很难对这个进行分类.我没有在SO上发现任何问题或在文档中解释任何相关的问题.怎么会被翻译成匿名课程?
我的怀疑是:
IntStream.generate(new IntSupplier() {
AtomicInteger atom = new AtomicInteger(1);
@Override
public int getAsInt() {
return atom.getAndIncrement();
}
})....
Run Code Online (Sandbox Code Playgroud)
......我不明白这是怎么回事.乍一看,我猜是表达式是:
IntStream.generate(new IntSupplier() {
@Override
public int getAsInt() {
return new AtomicInteger(1).getAndIncrement();
}
})....
Run Code Online (Sandbox Code Playgroud)
......但这不过是() -> new AtomicInteger(1).getAndIncrement().
这种表达式在哪里定义,以及如何在lambda/anonymous类中重写?
我可以理解为什么计算Total1,但是当计算Total2时我不知道!如何在BiFunction中使用BigDecimal :: add?签名不一样!!!
package br.com.jorge.java8.streams.bigdecimal;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
public class BigDecimalSumTest {
public static void main(String[] args) {
List<BigDecimal> list = new ArrayList<>();
list.add(new BigDecimal("1"));
list.add(new BigDecimal("2"));
BigDecimal total1 = list.stream().reduce(BigDecimal.ZERO, (t, v) -> t.add(v));
BigDecimal total2 = list.stream().reduce(BigDecimal.ZERO, BigDecimal::add);
System.out.println("Total 1: " + total1);
System.out.println("Total 2: " + total2);
}
}
Run Code Online (Sandbox Code Playgroud) 在我当前正在处理的一个 Java 项目中,我动态加载类,然后使用反射 API 来查找并执行那些具有某些注释的类的方法。
执行实际执行的代码专门根据 Java-8 功能接口工作(出于兼容性原因),因此我需要一个中间阶段,将Method使用反射发现的实例转换为适当的功能接口。我使用MethodHandleProxies类来实现这一点。
再次出于兼容性原因,所讨论的功能接口是通用接口。这会在使用该方法时导致“未经检查的转换”警告MethodHandleProxies.asInterfaceInstance,因为该方法返回“裸”接口。
以下是一个简短的示例,重现了所涉及的主要步骤:
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.Retention;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandleProxies;
import java.lang.invoke.MethodHandles;
import java.lang.reflect.Method;
import java.util.Arrays;
public class TestClass {
private String prefix;
public static void main(String[] args) throws IllegalAccessException, NoSuchMethodException, SecurityException {
// Use reflection to find method.
Method method = Arrays.stream(TestClass.class.getDeclaredMethods()) // Stream over methods of ConsumerClass
.filter(m -> m.isAnnotationPresent(Marker.class)) // Retain only methods with @Marker annotation
.findFirst().get(); // Get first such method …Run Code Online (Sandbox Code Playgroud) 我两次引用相同的方法,但引用不同。看这个例子:
import java.util.function.Consumer;
public class MethodRefTest {
public static void main(String[] args) {
new MethodRefTest();
}
public MethodRefTest() {
Consumer<Integer> a = this::method;
System.out.println(a);
Consumer<Integer> b = this::method;
System.out.println(b);
}
public void method(Integer value) {
}
}
Run Code Online (Sandbox Code Playgroud)
输出是:
MethodRefTest$$Lambda$1/250421012@4c873330
MethodRefTest$$Lambda$2/295530567@776ec8df
Run Code Online (Sandbox Code Playgroud)
方法引用只不过是匿名类的语法糖吗?如果不是,我该怎么做才能始终获得相同的方法引用?(除了在字段中存储一次参考以供使用之外。)
(应用:我认为方法引用是观察者实现的一种更漂亮的方式。但是每次使用不同的引用,一旦添加观察者就不可能从可观察者中删除观察者。)
考虑以下代码:
val hwnd = Handler()
hwnd.postDelayed(object : Runnable {
override fun run()
hwnd.postDelayed(this, 5000)
}
}, 5000)
Run Code Online (Sandbox Code Playgroud)
这样,我可以通过this在run()方法中使用(指的是 Runnable)将相同的 Runnable 发布到 Handler 。但是我怎么能只使用一个 lambda 表达式来做同样的事情呢?
val hwnd = Handler()
hwnd.postDelayed({
//How to get "this" here?
}, 5000)
Run Code Online (Sandbox Code Playgroud)
这甚至可能吗?
鉴于以下代码,有人可以解释为什么断言返回 true 吗?尽管已经进行了无数次搜索,但我无法得到任何适当的答案,说明为什么会出现这种情况,Java 特性是什么导致了这种行为,以及我在类似地创建这样的接口时会遇到哪些限制/要求作为这个。
interface X {
default int foo() {return 1;}
String bar();
}
public class Exercise{
public static void main(String[]arg){
X foo1=()->"hello";
assert (foo1.bar()).equals("hello");
}
}
Run Code Online (Sandbox Code Playgroud)