我使用的界面看起来像这样:
public interface ObjectListener {
public void objectAdded(Object o);
public void objectRemoved(Object o);
}
Run Code Online (Sandbox Code Playgroud)
我目前正在使用匿名类来实现接口,但我不关心这两种方法中的一种.有点像这样:
someObject.addListener(new ObjectListener() {
@Override
public void objectAdded(Object o) {
doSomething(o);
}
@Override
public void objectRemoved(Object o) {}
});
Run Code Online (Sandbox Code Playgroud)
现在,无论我在哪里,我都在Java 8中使用新的lambda表达式,并且我希望在这种情况下使用增加的简单性.毕竟,我只是实现了其中一个方法,但由于接口中有两个方法,我不能在lambda表达式中使用它.
有没有办法解决这个限制?
是否可以对集合执行多个映射?以下代码编译错误:
...在Stream中无法应用
java.util.function.Function<capture<?>,capture<?>>
private static List<?> multipleMapping(final Collection<?> collection, final List<Function<?, ?>> functions) {
Stream<?> stream = collection.stream();
for (Function<?, ?> function : functions) {
stream = stream.map(function);
}
return stream.collect(Collectors.toList());
}
Run Code Online (Sandbox Code Playgroud)
我想通用的解决方案.
通常,在大型项目的上下文中,将现有的,无处不在的接口用于功能接口是否安全?
例如,给定一个现有的接口和类:
public interface Interface {
public double calculateSomething(double x);
public void doSomething();
}
Run Code Online (Sandbox Code Playgroud)
由...实施
class InterfaceImplementer implements Interface {
public double calculateSomething(double x) {
return 2 * x;
}
public void doSomething() {
// insert specific behavior here
}
}
Run Code Online (Sandbox Code Playgroud)
我可以通过定义除一个方法之外的所有方法来安全地更改界面:
public interface Interface {
public double calculateSomething(double x);
default void doSomething() {
// insert some default behavior here
}
}
Run Code Online (Sandbox Code Playgroud)
这样我就可以将对象定义为
Interface object = new InterfaceImplementer() {
@Override
public double calculateSomething(double x) {
return 2 * x;
} …Run Code Online (Sandbox Code Playgroud) 我有一个重载方法,它将两个不同的功能接口作为参数(Runnble和Supplier).System.out.println显然只是兼容Runnable,因为它是一种void方法.然而,编译器仍然声称呼叫是模糊的.怎么可能?
import java.util.function.Supplier;
public class GenericLambdas {
public static void main(String[] args) {
wrap(System.out::println); // Compiler error here
wrap(() -> {}); // No error
wrap(System.out::flush); // No error
}
static <R> void wrap(Supplier<R> function) {}
static void wrap(Runnable function) {}
}
Run Code Online (Sandbox Code Playgroud)
编译器输出:
Error:Error:line (5)java: reference to wrap is ambiguous
both method <R>wrap(java.util.function.Supplier<R>) in GenericLambdas and method wrap(java.lang.Runnable) in GenericLambdas match
Error:Error:line (5)java: incompatible types: cannot infer type-variable(s) R
(argument mismatch; …Run Code Online (Sandbox Code Playgroud) 我需要使用基于布尔函数的谓词来组合流操作.通过将方法的参数重新抛出为谓词找到了一种解决方法,如下所示:
public <T> Predicate<T> pred(final Predicate<T> aLambda) {
return aLambda;
}
public List<String> foo() {
return new ArrayList<String>().stream() //of course, this does nothing, simplified
.filter(pred(String::isEmpty).negate())
.collect(Collectors.toList());
}
Run Code Online (Sandbox Code Playgroud)
'pred'方法似乎无能为力,但不是这样:
public List<String> foo() {
return new ArrayList<String>().stream()
.filter((String::isEmpty).negate())
.collect(Collectors.toList());
}
Run Code Online (Sandbox Code Playgroud)
也没有任何内联转换:
public List<String> foo() {
return new ArrayList<String>().stream()
.filter(((Predicate)String::isEmpty).negate())
.collect(Collectors.toList());
}
Run Code Online (Sandbox Code Playgroud)
似乎工作.失败了
此表达式的目标类型必须是功能接口
在'pred(...)'方法中,花式转换发生了什么?
我正在尝试通过BinaryOperator功能接口替换用于算术运算的公共开关.
基本方法是:
private static int computeOne(int res, String operand, String operation) {
int number = Integer.parseInt(operand);
switch (operation) {
case "+":
res += number;
break;
case "-":
res -= number;
break;
case "*":
res *= number;
break;
case "/":
res = (number != 0 ? res / number : Integer.MAX_VALUE);
break;
default:
res = 0;
System.out.println("unknown operation");
}
return res;
}
Run Code Online (Sandbox Code Playgroud)
据我所知,编写类似的内容是必要的:
BinaryOperator<Integer> action = (a,b) -> computeExpression(a + operation + b);
action.apply(res, operand);
Run Code Online (Sandbox Code Playgroud)
但我不明白如何避免switch与computeExpression …
该Callable和Supplier在功能接口java.util.concurrent和java.util.function包分别具有以下签名工具
public interface Callable<V> {
V call() throws Exception;
}
public interface Supplier<T> {
T get();
}
Run Code Online (Sandbox Code Playgroud)
是否有一些特定的用例,其中每一个都比另一个更适合?
我正在使用Java11.学习一种新的方法Predicate.not,我发现我目前的代码只找到猫科:
List<String> animals = List.of("cat", "leopard", "dog", "lion", "horse");
Predicate<String> cats = a -> !a.equals("dog") && !a.equals("horse");
Set<String> filterCat = animals.stream().filter(cats).collect(Collectors.toSet());
System.out.println(filterCat);
Run Code Online (Sandbox Code Playgroud)
输出是:
豹,猫,狮子
现在我正在尝试使用新方法,输出结果不正确.我该如何纠正?我做错了什么?
我后来的代码:
Predicate<String> updatedCatFilter = Predicate.not(a -> a.equals("dog") && a.equals("horse"));
Set<String> catFamily = animals.stream().filter(updatedCatFilter).collect(Collectors.toSet());
System.out.println(filterCat);
Run Code Online (Sandbox Code Playgroud)
但是现在输出我的所有列表.
马,豹,猫,狗,狮子
所以我熟悉 java 中的函数式接口,以及它们与 lambda 表达式的使用。一个函数式接口只能包含一个抽象方法。在 lambda 表达式中使用这个单独的方法时,您不需要指定它的名称 - 因为接口中只有一个抽象方法,编译器知道这是您正在引用的方法。
例子:
// Functional Interface:
@FunctionalInterface
public interface Ball
{
void hit();
}
// Lambda to define, then run the hit method:
Ball b = () -> System.out.println("You hit it!");
b.hit();
Run Code Online (Sandbox Code Playgroud)
虽然很明显为什么一个函数式接口只能包含一个抽象方法,但我不明白为什么不能重载那个方法。
例如,以下将无法编译:
// (NOT) Functional Interface:
@FunctionalInterface
public interface Ball
{
void hit();
void hit(boolean miss);
}
// Lambda to define, then run the hit method:
Ball b = () -> System.out.println("You hit it!");
Ball ba = (boolean miss) -> System.out.println(miss); …Run Code Online (Sandbox Code Playgroud) 我有以下代码:
new Thread(() -> {
//do things
}).start();
new Thread(() -> {
//do same things
}).start();
Run Code Online (Sandbox Code Playgroud)
我知道我可以声明一个包含lambda的函数:
Function<Integer, Integer> add = x -> x + 1;
Run Code Online (Sandbox Code Playgroud)
我想使此函数保留Runnablefrom的实现new Thread。
但我不知道该怎么放之间<>的Function。