Java 如何声明方法';s返回类型作为传递给方法的数组中最后一个lambda的返回类型

Java 如何声明方法';s返回类型作为传递给方法的数组中最后一个lambda的返回类型,java,lambda,java-8,Java,Lambda,Java 8,我要求一些我认为不可能的事情,如果是,我会删除这个问题 我有办法: public Object convertBy(Function... functions) { } 这些职能是: interface FLines extends Function { @Override default Object apply(Object t) { return null; }; public List<String> getLines(St

我要求一些我认为不可能的事情,如果是,我会删除这个问题

我有办法:

public Object convertBy(Function... functions) {
}
这些职能是:

interface FLines extends Function {
    @Override
    default Object apply(Object t) {
        return null;
    };

    public List<String> getLines(String fileName);
}

interface Join extends Function {
    @Override
    default Object apply(Object t) {
        return null;
    };

    public String join(List<String> lines);//lines to join
}

interface CollectInts extends Function {
    @Override
    default Object apply(Object t) {
        return null;
    };

    public List<Integer> collectInts(String s);
}

interface Sum<T, R> extends Function<T, R> {
    @Override
    default Object apply(Object t) {
        return null;
    };

    public R sum(T list);//list of Integers
}

主要方法:

   FLines<String, List<String>> flines ....

  Join<List<String>, String> join ...
  CollectInts<String, List<Integer>> collectInts ...

    Sum<List<Integer>, Integer> sum ...

String fname =/* System.getProperty("user.home") + "/*/ "LamComFile.txt"; 
InputConverter<String> fileConv = new InputConverter<>(fname);
List<String> lines =  fileConv.convertBy(flines);//cannot cast from Object to List<String>
String text =  fileConv.convertBy( join, flines);//cannot cast from Object to String
List<Integer> ints =   fileConv.convertBy(collectInts,flines, join);//cannot cast from Object to List<Integer>
Integer sumints =  fileConv.convertBy(sum, flines, join, collectInts);//works without cast!
FLines-FLines。。。。
加入加入。。。
集合集合集合。。。
求和。。。
字符串fname=/*System.getProperty(“user.home”)+“/*/”LamComFile.txt”;
InputConverter fileConv=新的InputConverter(fname);
List lines=fileConv.convertBy(flines);//无法从对象强制转换到列表
String text=fileConv.convertBy(join,flines);//无法从对象转换为字符串
List ints=fileConv.convertBy(collectInts、flines、join);//无法从对象强制转换到列表
整型sumints=fileConv.convertBy(sum、flines、join、collectionints);//无需强制转换即可工作!

我不明白为什么编译器理解
sum
返回的内容,但不推断例如
collectInts
返回的内容。

您必须更改方法签名并将最后一个vararg值作为单独的参数内联

如果将此参数作为最后一个参数,则无法使用vararg参数,因为它始终是最后一个参数,并且必须表示为数组,以防它不是最后一个:

public <T, R> R convertBy(Function[] functions, Function<T, R> special) { }

似乎您对泛型类型层次结构有一些误解。当您想要扩展泛型类型时,您必须对扩展类或接口的实际类型做出基本决定。您可以像中那样指定确切的类型

interface StringTransformer extends Function<String,String> {}
您正在扩展原始类型
函数
,并创建新的类型参数
,这些参数在您的场景中完全无用

为了继续上面的例子,您可以按如下方式实现它们

StringTransformer reverse = s -> new StringBuilder(s).reverse().toString();
NumberFunc<Integer> dbl = i -> i*2;
这可以以类型安全的方式使用:

FLines flines = name -> {
    try { return Files.readAllLines(Paths.get(name)); }
    catch(IOException ex) { throw new UncheckedIOException(ex); }
};
Join join = list -> String.join(",", list);
CollectInts collectInts=
    s -> Arrays.stream(s.split(",")).map(Integer::parseInt).collect(Collectors.toList());
Sum sum = l -> l.stream().reduce(0, Integer::sum);

InputConverter<String> fileConv = new InputConverter<>("LamComFile.txt");
List<String> lines = fileConv.convertBy(flines);
String text = fileConv.convertBy(flines.andThen(join));
List<Integer> ints = fileConv.convertBy(flines.andThen(join).andThen(collectInts));
Integer sumints = fileConv.convertBy(
    flines.andThen(join).andThen(collectInts).andThen(sum)
);
FLines-FLines=name->{
尝试{return Files.readAllLines(path.get(name));}
catch(IOException ex){抛出新的未选中的异常(ex);}
};
Join-Join=list->String.Join(“,”列表);
收藏品收藏品=
s->Arrays.stream(s.split(“,”).map(Integer::parseInt).collect(Collectors.toList());
Sum Sum=l->l.stream().reduce(0,整数::Sum);
InputConverter fileConv=新的InputConverter(“LamComFile.txt”);
列表行=fileConv.convertBy(flines);
String text=fileConv.convertBy(flines.andThen(join));
List ints=fileConv.convertBy(flines.andThen(join.andThen(collectionints));
整数sumints=fileConv.convertBy(
弗林斯。第四(加入)。第四(集合)。第四(总和)
);

感谢所有详细阐述此主题的人,您的解决方案在现实世界中会更好

作为作者,我想发布我的解决方案,它使
convertBy()
main()
中的调用不改变一位。它很短,很难看,但很有效

Main

Function<String, List<String>> flines ... lambda here

Function<List<String>, String> join ... lambda here

Function<String, List<Integer>> collectInts ... lambda here

Function<List<Integer>, Integer> sum ... lambda here


String fname = System.getProperty("user.home") + "/LamComFile.txt"; 
InputConverter<String> fileConv = new InputConverter<>(fname);
List<String> lines = fileConv.convertBy(flines);
String text = fileConv.convertBy(flines, join);
List<Integer> ints = fileConv.convertBy(flines, join, collectInts);
Integer sumints = fileConv.convertBy(flines, join, collectInts, sum);

System.out.println(lines);
System.out.println(text);
System.out.println(ints);
System.out.println(sumints);

List<String> arglist = Arrays.asList(args);
InputConverter<List<String>> slistConv = new InputConverter<>(arglist);  
sumints = slistConv.convertBy(join, collectInts, sum);
System.out.println(sumints); 

谢谢!它在main方法的4个位置中有3个有效。您能看一下编辑吗?我知道这是一种过于复杂的情况。这是因为您的所有功能(
FLines
Join
collections
)实现原始的
函数
界面。让它们实现
函数
或至少实现
函数
,这可以帮助您看到区别-当实现
函数
时,返回类型是
对象
,而不是
列表
,如
列表行=fileConv.convertBy(flines)
假设。谢谢。我(我认为)在编辑这些接口时做的第一件事是用
参数化的,我主要通过`Function flines=(flines)(fName)->{`解决了这个问题,但这是一种丑陋的方式。@Yoda:类型转换是不必要的。你可以简单地编写
Function flines=fName->{code}
,但当然,你的整个接口动物园都会过时。好吧,消除这些混乱只会让你的代码变得更好…@kocko你的解决方案很棒谢谢你,我实现了它,它起了作用,但不幸的是我无法更改
main()中
convertBy()的调用
。我提出了解决方案,并将其发布在下面,它不需要更改main。您能对此发表意见吗?我知道我忽略了一些泛型。“我不明白为什么编译器理解sum返回的值,但不推断例如collectInts返回的值。”-您可以通过查看类声明立即了解到这一点:
interface Sum extends Function
interface collections extends Function
…您确定
convertBy()
方法的主体是正确的吗?我认为它应该接受任意数量的参数(即
Function
)。目前没有必要使用vararg参数,因为您可以对
convertBy()
进行4次重载。这是一个将泛型与Java 8中引入的新语言功能结合使用的好例子。但是,他需要以以下方式准确地使用
convertBy()
fileConv.convertBy(sum,flines,join,collectInts);
@REACHUS:我认为OP不需要它的格式是
fileConv.convertBy(sum,flines,join,collectInts);
,否则,它很可能是一个XY问题……我担心这是一个XY问题,OP需要它的格式是完全相同的(除了它不是一种类型安全的方法)@REACHUS不幸的是,REACHUS是对的,我想改变主要内容并使用您的方法,因为它很棒(真的)我会自己研究它,但我不得不解决现实世界中不存在的问题,而且我无法改变调用
convertBy
方法的方式。因为这些方法似乎高度相关,所以我添加了一个。您不需要在
convertBy()
,就足够了。
interface FLines<T, R> extends Function
StringTransformer reverse = s -> new StringBuilder(s).reverse().toString();
NumberFunc<Integer> dbl = i -> i*2;
Function<String,Integer> f = reverse.andThen(Integer::valueOf).andThen(dbl);
System.out.println(f.apply("1234"));
interface FLines extends Function<String,List<String>> {
    @Override default List<String> apply(String fileName) {
        return getLines(fileName);
    }        
    public List<String> getLines(String fileName);
}
interface Join extends Function<List<String>,String> {
    @Override default String apply(List<String> lines) {
        return join(lines);
    }
    public String join(List<String> lines);
}
interface CollectInts extends Function<String,List<Integer>> {
    @Override default List<Integer> apply(String s) {
        return collectInts(s);
    }
    public List<Integer> collectInts(String s);
}
interface Sum extends Function<List<Integer>, Integer> {
    @Override default Integer apply(List<Integer> list) {
        return sum(list);
    }
    public Integer sum(List<Integer> list);
}
public class InputConverter<T> {

    private T value;

    public InputConverter(T value) {
        this.value = value;
    }
    public <R> R convertBy(Function<? super T, ? extends R> f) {
        return f.apply(value);
    }
}
FLines flines = name -> {
    try { return Files.readAllLines(Paths.get(name)); }
    catch(IOException ex) { throw new UncheckedIOException(ex); }
};
Join join = list -> String.join(",", list);
CollectInts collectInts=
    s -> Arrays.stream(s.split(",")).map(Integer::parseInt).collect(Collectors.toList());
Sum sum = l -> l.stream().reduce(0, Integer::sum);

InputConverter<String> fileConv = new InputConverter<>("LamComFile.txt");
List<String> lines = fileConv.convertBy(flines);
String text = fileConv.convertBy(flines.andThen(join));
List<Integer> ints = fileConv.convertBy(flines.andThen(join).andThen(collectInts));
Integer sumints = fileConv.convertBy(
    flines.andThen(join).andThen(collectInts).andThen(sum)
);
Function<String, List<String>> flines ... lambda here

Function<List<String>, String> join ... lambda here

Function<String, List<Integer>> collectInts ... lambda here

Function<List<Integer>, Integer> sum ... lambda here


String fname = System.getProperty("user.home") + "/LamComFile.txt"; 
InputConverter<String> fileConv = new InputConverter<>(fname);
List<String> lines = fileConv.convertBy(flines);
String text = fileConv.convertBy(flines, join);
List<Integer> ints = fileConv.convertBy(flines, join, collectInts);
Integer sumints = fileConv.convertBy(flines, join, collectInts, sum);

System.out.println(lines);
System.out.println(text);
System.out.println(ints);
System.out.println(sumints);

List<String> arglist = Arrays.asList(args);
InputConverter<List<String>> slistConv = new InputConverter<>(arglist);  
sumints = slistConv.convertBy(join, collectInts, sum);
System.out.println(sumints); 
public class InputConverter<T> {

    private T value;

    public InputConverter(T value) {
        this.value = value;
    }

    public <T, R> R convertBy(Function... functions) {
        Object result = value;
        for (int i = 0; i < functions.length; i++) {
            result = functions[i].apply(result);
        }
        return (R) result;
    }
}