例如(这是非常简化的),假设我在一副牌中有一个KingOfSpaces类,例如一个类,一个QueenOfSpades类,一个JackOfDiamonds类等等.所有这些都扩展了Card.可能有多个实例KingOfSpaces.
我有一个ArrayList<Card>,里面有5个物体.如何查看是否ArrayList至少包含一个AceOfDiamonds?
我想知道方法引用和功能接口的所有这些东西如何在较低级别上工作.最简单的例子是我们有一些List
List<String> list = new ArrayList<>();
list.add("b");
list.add("a");
list.add("c"):
Run Code Online (Sandbox Code Playgroud)
现在我们想用Collections类对它进行排序,所以我们可以调用:
Collections.sort(list, String::compareToIgnoreCase);
Run Code Online (Sandbox Code Playgroud)
但是,如果我们定义自定义比较器,它可能是这样的:
Comparator<String> customComp = new MyCustomOrderComparator<>();
Collections.sort(list, customComp::compare);
Run Code Online (Sandbox Code Playgroud)
问题是Collections.sort有两个参数:List和Comparator.由于Comparator是功能接口,因此可以使用具有相同签名(参数和返回类型)的lambda表达式或方法引用替换它.那么它是如何工作的,我们也可以传递compareTo只引用一个参数并且这些方法的签名不匹配?如何在Java8中翻译方法引用?
我在使用jre1.8.0_66的代码运行中遇到这个奇怪的异常:
Exception in thread "main" java.lang.BootstrapMethodError: call site initialization exception
at java.lang.invoke.CallSite.makeSite(CallSite.java:341)
at java.lang.invoke.MethodHandleNatives.linkCallSiteImpl(MethodHandleNatives.java:307)
at java.lang.invoke.MethodHandleNatives.linkCallSite(MethodHandleNatives.java:297)
at main
Caused by: java.lang.invoke.LambdaConversionException: Invalid receiver type class java.lang.Object; not a subtype of implementation type interface Fruit
at java.lang.invoke.AbstractValidatingLambdaMetafactory.validateMetafactoryArgs(AbstractValidatingLambdaMetafactory.java:233)
at java.lang.invoke.LambdaMetafactory.metafactory(LambdaMetafactory.java:303)
at java.lang.invoke.CallSite.makeSite(CallSite.java:302)
... 3 more
Run Code Online (Sandbox Code Playgroud)
这是什么意思?代码如下:
public static interface Fruit {
int getPickingMonth();
}
public static class Apple implements Fruit, Serializable {
@Override
public int getPickingMonth() {
return 11;
}
}
public static class Orange implements Fruit, Serializable {
@Override
public int …Run Code Online (Sandbox Code Playgroud) 例如,为什么我可以写行
Character[] c = Arrays.sort(list.toArray(new Character[list.size()]))
Run Code Online (Sandbox Code Playgroud)
但是在我阅读有关方法引用的文档时,它们会告诉我使用它::吗?它不和.运营商一样吗?
我不知道上面的代码是否编译,因为我在我的手机上输入了这个.把它看作一个松散的例子.
我不明白如何使用lambdas将方法作为参数传递.
考虑以下(不编译)代码,如何完成它以使其工作?
public class DumbTest {
public class Stuff {
public String getA() {
return "a";
}
public String getB() {
return "b";
}
}
public String methodToPassA(Stuff stuff) {
return stuff.getA();
}
public String methodToPassB(Stuff stuff) {
return stuff.getB();
}
//MethodParameter is purely used to be comprehensive, nothing else...
public void operateListWith(List<Stuff> listStuff, MethodParameter method) {
for (Stuff stuff : listStuff) {
System.out.println(method(stuff));
}
}
public DumbTest() {
List<Stuff> listStuff = new ArrayList<>();
listStuff.add(new Stuff());
listStuff.add(new Stuff());
operateListWith(listStuff, methodToPassA); …Run Code Online (Sandbox Code Playgroud) 编辑:我的问题在这里得到了解答.总而言之,我对非静态方法引用的使用感到困惑.功能接口和参考方法具有不同数量的参数.
回答我的问题的是评论和接受的答案.
我目前正在阅读关于流减少方法的Java教程(https://docs.oracle.com/javase/tutorial/collections/streams/reduction.html).在那里,我发现了一段我认为错误的代码,所以我做了一个更简单的代码来确保.
// B.java file
import java.util.*;
public class B
{
public static void main(String[] args)
{
List<Integer> zahlen = new LinkedList<Integer>();
zahlen.add(1);
zahlen.add(2);
zahlen.add(3);
Averager averageCollect = zahlen.stream()
.collect(Averager::new, Averager::addcount, Averager::combine);
System.out.println(averageCollect.average());
}
}
// Averager.java from the official Java tutorial
public class Averager
{
private int total = 0;
private int count = 0;
public double average() {
return count > 0 ? ((double) total)/count : 0;
}
public void addcount(int i) { …Run Code Online (Sandbox Code Playgroud) 这是Java 8中::(双冒号)运算符的后续问题,其中Java允许您使用::运算符引用方法.
是否可以提供我创建的一些自定义功能接口并将其与::运营商一起使用?怎么做?
我正在研究使用1.8对Java SE API所做的一些更改,我在查看新方法 Map.merge时,它显示了如何将其与行一起使用的示例
map.merge(key, msg, String::concat)
Run Code Online (Sandbox Code Playgroud)
我理解如何使用lambda表达式来创建匿名功能接口,但这似乎使用一个方法作为BiFunction.我喜欢理解和使用晦涩的java语法,但我无法在任何地方找到任何提及.
我正在使用lamdbas,所以我可以根据我可以从三个不同对象检索的值一致地设置ModelObject的属性.代码的工作原理如下:
public class Processor {
private void bar(Setter setter, MyClass myObject) {
String variable = myObject.getStringByABunchOfMethods();
setter.setVariable(variable);
}
protected void foo(...) {
...
bar(value -> model.setA(CONSTANT, value), aObject);
bar(value -> model.setB(value), bObject);
bar(value -> model.setC(value), cObject);
...
}
private interface Setter {
public void setVariable(String string);
}
}
public interface IModel {
public void setA(String arg0, String arg1);
public void setB(String arg0);
public void setC(String arg0);
}
Run Code Online (Sandbox Code Playgroud)
我已阅读在这里,有可能改写bar(value -> model.setB(value), bObject);到bar(model::setB, bObject).我认为这看起来更好,更简洁,但我还没有找到一种方法将setA方法重写为double …
我有一个矩阵类,我想在这个类中创建一个名为 map 的函数,它看起来像这样
public void map(T fn) {
//do something
}
Run Code Online (Sandbox Code Playgroud)
该函数背后的想法是作为参数 fn,它可以是任何方法并将此方法应用于矩阵中的每个数字。
它背后的想法是针对神经网络上的编码训练视频,但我尝试在 Java 中对其进行操作,但没有奏效。我搜索 lambda 表达式,但是当我使用它时,它只让我传递像 Math.cos(arg ) 里面有一个参数。但我希望它在没有任何参数的情况下传递当前函数看起来像这样
interface lambda<T> {
double foo(T fn);
}
public void map(T fn) {
for(int i = 0 ; i< this.getRow() ; i++) {
for(int j = 0 ; j< this.getCol(); j++) {
int a = i;
int b = j;
lambda mycode = (T) -> setData(matrix[a][b], fn);
matrix[i][j] = mycode.foo(fn);
}
}
}
private double setData(double data, T fn) { …Run Code Online (Sandbox Code Playgroud)