在流收集器中组合Java 8方法引用

4

我希望能够在流的collect(Collectors.toMap(..))调用中组合方法引用。在下面的示例中,我有一段代码可以完成我的任务,但没有方法引用:

class A {
    private String property1;
    private B property2;

    public String getProperty1() { return property1; }
    public B getProperty2() { return property2; }
}

class B {
    private String property3;

    public String getProperty3() { return property3; }
}

public class Main {
    public static void Main() {
        List<A> listOfA = /* get list */;

        Map<String, String> = listOfA.stream()
            .collect(toMap(x -> x.getProperty1(), x -> x.getProperty2().getProperty3()));
    } 
}

x -> x.getProperty1()更改为A::getProperty1()非常简单。然而,x -> x.getProperty2().getProperty3()则不那么简单。我希望以下其中一种方法可行:

.collect(toMap(A::getProperty1, ((Function)A::getProperty2).andThen((Function)B::getProperty3)))

或者
.collect(toMap(A::getProperty1, ((Function)B::getProperty3).compose((Function)A::getProperty2)))

然而,它们都给我报了“非静态方法无法从静态上下文中引用”的错误。

3
没有更好的方法来做这件事。原始lambda表达式是你能得到的最好的选择。 - Louis Wasserman
4
你最终得到的每个答案都会比Lambda表达式更冗长、笨重,难以阅读。为什么你想要使用其他方式? - Tunaki
我主要是出于好奇在探索这个问题,至少是在这个特定的问题表述下。即使我提供的两个例子(它们都无法工作)也比Lambda更笨拙和不易读取。然而,方法组合是一个强大的特性,如果可能的话,我会更经常使用它。如果你们中的任何一个人能够解释为什么不允许这样做,并且在哪些情况下我可以使用方法组合(例如,如果所有方法都是静态的,是否可能?),那将非常有用,也值得接受的答案。无论如何,谢谢! - Lev Dubinets
3
我不认为有任何情况下可以不用强制转换来完成。问题在于A :: getProperty2 可能是任何一个功能接口,它具有一个返回 java.util.function.FunctionandThen 方法,而Java无法为您推断出它的类型。 - Louis Wasserman
7
方法引用是一种对于非常受限的一组 lambda 表达式的简写方式。每个人第一次遇到它们时,都希望找到扩展它们覆盖更多情况的方法(例如链接、绑定参数等)——但一旦你超越了仅仅命名一个方法的程度,收益就不存在了,这就是简写结束的地方。 - Brian Goetz
1个回答

4

A::getProperty2是一个Function<A, B>函数(即一个接受A的实例并返回B的实例的函数)。

您可以将其进行强制类型转换和组合,如下:

((Function<A, B>)A::getProperty2).andThen(B::getProperty3)

或者您可以创建一个类似于函数的生产者:

public static <A, B, R> Function<A, R> compose(
        Function<A, B> f1, Function<B, R> f2) {
    return f1.andThen(f2);
}

然后使用它来组合如下:

compose(A::getProperty2, B::getProperty3)

1
"A::getProperty2" 是一个有效的 Function 方法引用,但它不能作为 Supplier 使用,因为它接受一个类型为 A 的参数。 - Didier L
所以我的错误是将其转换为Function而不是您澄清的Function<A,B>。谢谢! - Lev Dubinets

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接