gpt4 book ai didi

java - 在列表上映射通用方法并生成结果列表

转载 作者:行者123 更新时间:2023-11-30 11:24:24 25 4
gpt4 key购买 nike

我有一个通用方法(称为 map ),它采用 Funcn 类型的参数其中 Funcn<K,T>是一个只有一个方法的接口(interface),T eval(K) ,它需要一个 K并返回 T .在 map , 我需要使用 Funcn遍历 List<K> (这是在 main 方法中定义的——我在 this 中使用 map 来访问它)并应用 Funcn到列表中的每个元素。最后,一个新的 List<T> eval 的所有结果应该退回。但是,我不确定如何做到这一点,因为我不熟悉泛型的语法。

/// the Funcn interface ///
package arrayList;
import java.util.*;

public interface Funcn <K,T> {
public T eval(K k);
}

/// the generic map method(in its own class) ///
public java.util.ArrayList<T> map(Funcn<T,K> fn){
for(T value:this){
//fn must be applied to all elements in 'this'
}
}

最佳答案

代码中的问题

在您的代码中,接口(interface) Funcn<K,T>声明一个方法 eval这需要 K作为参数并返回 T .注意 K是第一个类型参数,T是第二个。

public interface Funcn <K,T> {
public T eval(K k);
}

在您的声明中map方法,但是,您已经获得了 Funcn 的类型参数反转:

public java.util.ArrayList<T> map(Funcn<T,K> fn){ /* … */ }
// * *

这意味着fn.eval需要 T并返回 K .相反,它应该是 Funcn<K,T> fn这样fn.eval需要 K并返回 T .这将解释您在评论中提到的错误消息:“类型 apply(K) 中的方法 Function<T,K> 不适用于参数 (T) ”(它不会解释为什么您有 Function 在不过,一个地方和另一个地方的 Funcn。您向我们展示了真正的代码吗?)

一般情况

交换这些参数的顺序将解决您眼前的问题,但通常类型参数会稍微复杂一些。要完全正确地获取这些泛型函数的输入和输出类型是很棘手的,因为您应该能够将期望类型 C 的参数的函数映射到其元素是 C 的子类型的列表上。代码中的注释解释了这一点更详细一些。

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class MapExample {

/**
* A Function maps an input to an output.
*/
interface Function<InputType,OutputType> {
OutputType call( InputType input );
}

/**
* Map returns a list of elements obtained by applying the function
* to each element of the input list. The input and output types
* of the function do not need to align exactly with the type of
* elements in the input list; but the function's input type must
* be some supertype of the element type of the input list. Similarly,
* the output type of the function does not need to be the element type
* of the output list; but it must extend that type so that the result
* of the function can be stored in the output list.
*/
public static <OutputType,InputType> List<OutputType> map(
final Function<? super InputType,? extends OutputType> function,
final List<? extends InputType> list ) {
final List<OutputType> results = new ArrayList<>( list.size() );
for ( InputType in : list ) {
results.add( function.call( in ));
}
return results;
}

public static void main(String[] args) {
// f takes an integer n to the string "*<n+1>*" (where <n+1> is the value of n+1).
Function<Integer,String> f = new Function<Integer, String>() {
@Override
public String call(Integer input) {
return "*"+new Integer( input + 1 ).toString()+"*";
}
};
System.out.println( map( f, Arrays.asList( 1, 3, 6, 8 )));
}
}

输出是:

[*2*, *4*, *7*, *9*]

(可选)实例初始化器的案例

顺便说一句,我发现其中一些功能性问题是在对象中使用实例初始化 block 的好地方。虽然上面的实现创建了 results列出,然后填充,然后返回它,您还可以拥有 map 的正文是:

return new ArrayList<OutputType>( list.size() ) {{
for ( final InputType in : list ) {
add( function.call( in ));
}
}};

我有点喜欢,尽管您会收到一条警告,指出新的(匿名)类没有序列化 ID,因此您要么需要 @SuppressWarnings("serial")map 上方法,或向类添加一个 ID。不过,这些可能不太理想。不过,如 Efficiency of Java "Double Brace Initialization"? 中所讨论,此类对象也存在其他问题。 .

关于java - 在列表上映射通用方法并生成结果列表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20685017/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com