【问题标题】:Can a java lambda have more than 1 parameter?java lambda 可以有超过 1 个参数吗?
【发布时间】:2015-03-08 11:19:42
【问题描述】:

在 Java 中,是否可以让 lambda 接受多种不同的类型?

即: 单变量有效:

    Function <Integer, Integer> adder = i -> i + 1;
    System.out.println (adder.apply (10));

可变参数也可以:

    Function <Integer [], Integer> multiAdder = ints -> {
        int sum = 0;
        for (Integer i : ints) {
            sum += i;
        }
        return sum;
    };

    //.... 
    System.out.println ((multiAdder.apply (new Integer [] { 1, 2, 3, 4 })));

但我想要一些可以接受许多不同类型参数的东西,例如:

    Function <String, Integer, Double, Person, String> myLambda = a , b, c, d->  {
    [DO STUFF]
    return "done stuff"
    };

主要用途是为了方便起见,在函数内部有小的内联函数。

我环顾了谷歌并检查了 Java 的函数包,但找不到。这可能吗?

【问题讨论】:

    标签: java lambda java-8


    【解决方案1】:

    如果您使用多个类型参数定义这样的功能接口,这是可能的。没有这样的内置类型。 (有几个有限的类型有多个参数。)

    @FunctionalInterface
    interface Function6<One, Two, Three, Four, Five, Six> {
        public Six apply(One one, Two two, Three three, Four four, Five five);
    }
    
    public static void main(String[] args) throws Exception {
        Function6<String, Integer, Double, Void, List<Float>, Character> func = (a, b, c, d, e) -> 'z';
    }
    

    我在这里称它为Function6。名称由您自行决定,尽量不要与 Java 库中的现有名称发生冲突。


    也没有办法定义可变数量的类型参数,如果这就是你要问的。


    一些语言,如 Scala,定义了许多内置的此类类型,具有 1、2、3、4、5、6 等类型参数。

    【讨论】:

    • 你可以随时使用柯里化:Function&lt;One, Function&lt;Two, Function&lt;Three, Function&lt;Four, Function&lt;Five, Six&gt;&gt;&gt;&gt;&gt; func = a -&gt; b -&gt; c -&gt; d -&gt; e -&gt; 'z';
    • 柯里化?哇,这比功能界面差多了。
    【解决方案2】:

    对于有 2 个参数的东西,您可以使用 BiFunction。如果您需要更多,您可以定义自己的函数接口,如下所示:

    @FunctionalInterface
    public interface FourParameterFunction<T, U, V, W, R> {
        public R apply(T t, U u, V v, W w);
    }
    

    如果有多个参数,则需要在参数列表周围加上括号,如下所示:

    FourParameterFunction<String, Integer, Double, Person, String> myLambda = (a, b, c, d) -> {
        // do something
        return "done something";
    };
    

    【讨论】:

      【解决方案3】:

      对于这种情况,您可以使用默认库 (java 1.8) 中的接口:

      java.util.function.BiConsumer
      java.util.function.BiFunction
      

      接口中有一个小的(不是最好的)默认方法示例:

      default BiFunction<File, String, String> getFolderFileReader() {
          return (directory, fileName) -> {
              try {
                  return FileUtils.readFile(directory, fileName);
              } catch (IOException e) {
                  LOG.error("Unable to read file {} in {}.", fileName, directory.getAbsolutePath(), e);
              }
              return "";
          };
      }}
      

      【讨论】:

      • 如果您修改问题以说明如何使用这些接口来满足要求,您将获得更多 Java8 粉丝的支持。
      • BiFunction 只允许定义两个参数的函数,问题是关于具有任意数量参数的函数
      • 这适用于我的应用程序。尽可能使用内置接口是件好事!
      【解决方案4】:

      要使用 lambda :有三种操作:
      1. 接受参数 --> Consumer
      2. 测试参数返回布尔值 --> Predicate
      3. 操作参数和返回值 --> 函数

      Java 函数式接口最多两个参数:
      单参数接口
      消费者
      谓词
      功能

      二参数界面
      双消费者
      双谓词
      双功能

      两个以上,你必须创建如下功能接口(消费者类型):

      @FunctionalInterface
      public interface FiveParameterConsumer<T, U, V, W, X> {
          public void accept(T t, U u, V v, W w, X x);
      }
      

      【讨论】:

        【解决方案5】:

        您也可以使用 jOOL 库 - https://github.com/jOOQ/jOOL

        已经准备了不同数量参数的函数接口。例如,您可以使用org.jooq.lambda.function.Function3 等从Function0Function16

        【讨论】:

        • 另一个提供类似预定义接口的流行库是Vavr
        【解决方案6】:

        另一种选择,不确定这是否适用于您的特定问题,但可能适用于某些问题,即在 java.util.function 库中使用UnaryOperator。 它返回您指定的相同类型,因此您将所有变量放在一个类中,并将其作为参数:

        public class FunctionsLibraryUse {
        
            public static void main(String[] args){
                UnaryOperator<People> personsBirthday = (p) ->{
                    System.out.println("it's " + p.getName() + " birthday!");
                    p.setAge(p.getAge() + 1);
                    return p;
                };
                People mel = new People();
                mel.setName("mel");
                mel.setAge(27);
                mel = personsBirthday.apply(mel);
                System.out.println("he is now : " + mel.getAge());
        
            }
        }
        class People{
            private String name;
            private int age;
            public String getName() {
                return name;
            }
            public void setName(String name) {
                this.name = name;
            }
            public int getAge() {
                return age;
            }
            public void setAge(int age) {
                this.age = age;
            }
        }
        

        因此,您拥有的类(在本例中为 Person)可以有许多实例变量,并且不必更改 lambda 表达式的参数。

        对于那些感兴趣的人,我已经写了关于如何使用 java.util.function 库的注释:http://sysdotoutdotprint.com/index.php/2017/04/28/java-util-function-library/

        【讨论】:

          【解决方案7】:

          一些 lambda 函数:

          import org.junit.Test;
          import java.awt.event.ActionListener;
          import java.util.function.Function;
          
          public class TestLambda {
          
          @Test
          public void testLambda() {
          
              System.out.println("test some lambda function");
          
              ////////////////////////////////////////////
              //1-any input | any output:
              //lambda define:
              Runnable lambda1 = () -> System.out.println("no parameter");
              //lambda execute:
              lambda1.run();
          
          
              ////////////////////////////////////////////
              //2-one input(as ActionEvent) | any output:
              //lambda define:
              ActionListener lambda2 = (p) -> System.out.println("One parameter as action");
              //lambda execute:
              lambda2.actionPerformed(null);
          
          
              ////////////////////////////////////////////
              //3-one input | by output(as Integer):
              //lambda define:
              Function<String, Integer> lambda3 = (p1) -> {
                  System.out.println("one parameters: " + p1);
                  return 10;
              };
              //lambda execute:
              lambda3.apply("test");
          
          
              ////////////////////////////////////////////
              //4-two input | any output
              //lambda define:
              TwoParameterFunctionWithoutReturn<String, Integer> lambda4 = (p1, p2) -> {
                  System.out.println("two parameters: " + p1 + ", " + p2);
              };
              //lambda execute:
              lambda4.apply("param1", 10);
          
          
              ////////////////////////////////////////////
              //5-two input | by output(as Integer)
              //lambda define:
              TwoParameterFunctionByReturn<Integer, Integer> lambda5 = (p1, p2) -> {
                  System.out.println("two parameters: " + p1 + ", " + p2);
                  return p1 + p2;
              };
              //lambda execute:
              lambda5.apply(10, 20);
          
          
              ////////////////////////////////////////////
              //6-three input(Integer,Integer,String) | by output(as Integer)
              //lambda define:
              ThreeParameterFunctionByReturn<Integer, Integer, Integer> lambda6 = (p1, p2, p3) -> {
                  System.out.println("three parameters: " + p1 + ", " + p2 + ", " + p3);
                  return p1 + p2 + p3;
              };
              //lambda execute:
              lambda6.apply(10, 20, 30);
          
          }
          
          
          @FunctionalInterface
          public interface TwoParameterFunctionWithoutReturn<T, U> {
              public void apply(T t, U u);
          }
          
          @FunctionalInterface
          public interface TwoParameterFunctionByReturn<T, U> {
              public T apply(T t, U u);
          }
          
          @FunctionalInterface
          public interface ThreeParameterFunctionByReturn<M, N, O> {
              public Integer apply(M m, N n, O o);
          }
          }
          

          【讨论】:

            猜你喜欢
            • 2022-11-17
            • 1970-01-01
            • 2020-07-30
            • 2015-09-20
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多