简体   繁体   English

Java流API将lambda表达式存储为变量

[英]Java Stream API storing lambda expression as variable

This title sounds stupid even to me, but there must be at least somewhat clever way to achieve such effect and I don't know how else to explain it. 这个标题对我来说听起来很愚蠢,但必须至少有一些聪明的方法才能达到这样的效果,我不知道怎么解释它。 I need to sort array using sorted in stream API. 我需要使用sorted in stream API对数组进行排序。 Here is my stream so far: 到目前为止,这是我的流:

Arrays.stream(sequence.split(" "))
        .mapToInt(Integer::parseInt)
        .boxed()
        .sorted((a, b) -> a.compareTo(b))
        .forEach(a -> System.out.print(a + " "));

Now I have two different sorts of course - ascending and descending and the sort I need to use is specified in the user input. 现在我有两种不同的过程 - 升序和降序,我需要使用的排序在用户输入中指定。 So what I want to do is having something like switch with 2 cases: "ascending" and "descending" and a variable to store the lambda expression respectively: 所以我想做的就是切换2个案例:“升序”和“降序”以及分别存储lambda表达式的变量:

switch(command) {
    case "ascending": var = a.compareTo(b);
    case "descending": var = b.compareTo(a);
}

Then I my sorted looks like: 然后我的排序看起来像:

 .sorted((a, b) -> var)

I got the idea in a python course I attended. 我在参加的python课程中得到了这个想法。 There it was available to store an object in variable, thus making the variable "executable". 在那里可以将对象存储在变量中,从而使变量“可执行”。 I realize that this lambda is not an object, but an expression, but I'm asking is there any clever way that can achieve such result, or should I just have 我意识到这个lambda不是一个对象,而是一个表达式,但我要问的是有什么聪明的方法可以达到这样的结果,或者我应该只有

if(var)

and two diferent streams for each sort order. 每个排序顺序有两个不同的流。

You can switch between using Comparator.reverseOrder() and Comparator.naturalOrder : 您可以在使用Comparator.reverseOrder()Comparator.naturalOrder之间切换:

Comparator<Integer> comparator = youWantToHaveItReversed ? Comparator.reverseOrder(): Comparator.naturalOrder();
Arrays.stream(sequence.split(" "))
      .map(Integer::valueOf)
      .sorted(comparator)
      .forEach(a -> System.out.print(a + " "));

The question is not stupid at all. 这个问题根本不是愚蠢的。 Answering it in a broader sense: Unfortunately, there is no generic solution for that. 从更广泛的意义上回答:不幸的是,没有通用的解决方案。 This is due to the type inference, which determines one particular type for the lambda expression, based on the target type. 这是由于类型推断,它根据目标类型确定lambda表达式的一种特定类型。 (The section about type inference may be helpful here, but does not cover all details regarding lambdas). (关于类型推断的部分在这里可能会有所帮助,但不包括有关lambdas的所有细节)。

Particularly, a lambda like x -> y does not have any type. 特别是,像x -> y这样的lambda没有任何类型。 So there is no way of writing 所以没有办法写作

GenericLambdaType function = x -> y; GenericLambdaType function = x -> y;

and later use function as a drop-in replacement for the actual lambda x -> y . 然后使用function作为实际lambda x -> y替代品。

For example, when you have two functions like 例如,当你有两个函数时

static void useF(Function<Integer, Boolean> f) { ... }
static void useP(Predicate<Integer> p) { ... }

you can call them both with the same lambda 你可以用同一个lambda来调用它们

useF(x -> true);
useP(x -> true);

but there is no way of "storing" the x -> true lambda in a way so that it later may be passed to both functions - you can only store it in a reference with the type that it will be needed in later: 但是没有办法以某种方式“存储” x -> true lambda,以便以后可以将它传递给两个函数 - 你只能将它存储在一个引用中, 引用具有以后需要的类型

Function<Integer, Boolean> f = x -> true;
Predicate<Integer>         p = x -> true;
useF(f);
useP(p);

For your particular case, the answer by Konstantin Yovkov already showed the solution: You have to store it as a Comparator<Integer> (ignoring the fact that you wouldn't have needed a lambda here in the first place...) 对于您的特定情况, Konstantin Yovkov答案已经显示了解决方案:您必须将其存储为Comparator<Integer> (忽略您首先不需要lambda的事实......)

In Lambdas you can use a functionblock (a,b) -> { if(anything) return 0; else return -1;} 在Lambdas中你可以使用一个功能块(a,b) -> { if(anything) return 0; else return -1;} (a,b) -> { if(anything) return 0; else return -1;}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM