关于Java函数式编程的问题

问题描述 投票:0回答:2

这是我的代码:

static String underscoreToCamel(String str) {
        UnaryOperator<String> capitalize = s -> s.substring(0, 1).toUpperCase() + s.substring(1).toLowerCase();
        
        Seq<UnaryOperator<String>> seq = c -> {
            c.accept(String::toLowerCase);
            while (true) {
                c.accept(capitalize);
            }
        };
        List<String> split = Arrays.asList(str.split("_"));
        Seq<String> s1 = seq.zip(split, Function::apply);
        String a = s1.join("");
        return a;
    }

public interface Seq<T> {
        void consume(Consumer<T> consumer);

        static <T> Seq<T> unit(T t) {
            return consumer -> consumer.accept(t);
        }

        default <E> Seq<E> map(Function<T, E> function) {
            return consumer -> consume(t -> consumer.accept(function.apply(t)));
        }

        default <E> Seq<E> flatMap(Function<T, Seq<E>> function) {
            return consumer -> consume(t -> function.apply(t).consume(consumer));
        }


        default String join(String sep) {
            StringJoiner joiner = new StringJoiner(sep);
            consume(t -> joiner.add(t.toString()));
            return joiner.toString();
        }

        static <T> T stop() {
            throw StopException.INSTANCE;
        }

        default void consumeTillStop(Consumer<T> consumer) {
            try {
                consume(consumer);
            } catch (StopException ignore) {}
        }

        default <U, R> Seq<R> zip(Iterable<U> iterable, BiFunction<T, U, R> function) {
            return c -> {
                Iterator<U> iterator = iterable.iterator();
                consumeTillStop(t -> {
                    if (iterator.hasNext()) {
                        c.accept(function.apply(t, iterator.next()));
                    } else {
                        stop();
                    }
                });
            };
        }

    }

我不明白这行的逻辑

Seq<String> s1 = seq.zip(split, Function::apply);
,这个
Function::apply
是什么意思

我知道这是一个方法引用,但不知道这个引用的实例是什么

java lambda method-reference
2个回答
1
投票

这确实是一个有趣的,因为它使用了方法引用允许的

shortcuts

之一。 快速示例,假设您需要一个

Function<String, Integer>

,那么可以写

String::length
,尽管此方法具有不同的签名。要求的签名是:
Integer apply(String x) { ... }

但是我们提供了一个只有
int length()

的方法,所以根本没有

String
参数。但是,该方法是非静态的,并且对
String
的实例进行操作。因此 java 可以假定您打算在该实例上调用该方法,并由此推断出该方法的第一个参数。 IE。
s -> s.length()
.

一般细节

您的设置中也发生了同样的情况。首先,您必须了解您所请求的

BiFunction<T, U, R>

的泛型解决了什么问题。他们是:


    T
  • UnaryOperator<String>
  • U
  • String
  • R
  • Consumer<T>
    ,所以
    Consumer<UnaryOperator<String>>
    
    
  • 实际签名

相当复杂,但没关系。现在,请求的签名是:

Consumer<UnaryOperator<String>> apply(UnaryOperator<String> t, String u)

现在,当你给出你的方法参考
Function::apply

,其签名是:

R apply(T t)

所以,在这种情况下:

Consumer<UnaryOperator<String>> apply(String u)

并且所需签名 (
UnaryOperator<String> t

) 的第一个参数再次从

Function::apply
是一个在
Function
实例上运行的非静态方法这一事实中推导出来,它恰好与
UnaryOperator<String>
兼容,因为
UnaryOperator implements Function
.
实施

所以

Function::apply

本质上与将您的

BiFunction
实现为:
Consumer<UnaryOperator<String>> apply(UnaryOperator<String> t, String u) {
  return t.apply(u);
}



0
投票
Function::apply

是方法引用,指的是

Seq s1 = seq.zip(split, Function::apply)
行中Function接口的apply方法。它作为 zip 方法的第二个参数,它需要一个
BiFunction
函数接口,并预期一个接受两个类型为
T
U
的参数并返回一个类型为
R
的结果。
在这个例子中,

T

是一个

UnaryOperator<String>
(来自
Seq<UnaryOperator<String>> seq)
U
是一个String(来自
List<String> split
),而
R
在执行zip方法时是一个String。因为
String::apply
与 Function 接口的 apply 方法具有相同的签名,它接受一个 String 类型的参数并返回一个 String,它被用作对
Function::apply
方法的引用。
seq 函数序列将通过 zip 方法应用于拆分列表的每个元素,因为迭代拆分列表的元素。 Function 接口的 apply 方法将用于将 seq 中的每个

UnaryOperator<String>

应用到 split 中相应的 String 元素。

    

© www.soinside.com 2019 - 2024. All rights reserved.