Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/373.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/heroku/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Java中简化流上的Lambda表达式_Java_Lambda_Java Stream - Fatal编程技术网

在Java中简化流上的Lambda表达式

在Java中简化流上的Lambda表达式,java,lambda,java-stream,Java,Lambda,Java Stream,我试图教自己如何在Java中使用lambda表达式,而不是常规的外部迭代类型解决方案。我做了一个简短的程序,我用一个整数流给它们赋值。我没有使用典型的“switch”语句,而是使用了这些lambda表达式。有什么方法可以简化它吗?看来有更好的办法。它能工作,但看起来不那么整洁 grades.stream() .mapToInt(Integer::intValue) .filter(x -> x >= 90) .for

我试图教自己如何在Java中使用lambda表达式,而不是常规的外部迭代类型解决方案。我做了一个简短的程序,我用一个整数流给它们赋值。我没有使用典型的“switch”语句,而是使用了这些lambda表达式。有什么方法可以简化它吗?看来有更好的办法。它能工作,但看起来不那么整洁

    grades.stream()
          .mapToInt(Integer::intValue)
          .filter(x -> x >= 90)
          .forEach(x -> System.out.println(x + " -> A"));

    grades.stream()
          .mapToInt(Integer::intValue)
          .filter(x -> x >= 80 && x <= 89)
          .forEach(x -> System.out.println(x + " -> B"));

    grades.stream()
          .mapToInt(Integer::intValue)
          .filter(x -> x >= 70 && x <= 79)
          .forEach(x -> System.out.println(x + " -> C"));

    grades.stream()
          .mapToInt(Integer::intValue)
          .filter(x -> x >= 60 && x <= 69)
          .forEach(x -> System.out.println(x + " -> D"));

    grades.stream()
          .mapToInt(Integer::intValue)
          .filter(x -> x >= 50 && x <= 59)
          .forEach(x -> System.out.println(x + " -> F"));
grades.stream()
.mapToInt(整数::intValue)
.过滤器(x->x>=90)
.forEach(x->System.out.println(x+“->A”);
等级.溪流()
.mapToInt(整数::intValue)
.filter(x->x>=80&&x System.out.println(x+“->B”);
等级.溪流()
.mapToInt(整数::intValue)
.filter(x->x>=70&&x System.out.println(x+“->C”);
等级.溪流()
.mapToInt(整数::intValue)
.filter(x->x>=60&&x System.out.println(x+“->D”);
等级.溪流()
.mapToInt(整数::intValue)
.filter(x->x>=50&&x System.out.println(x+“->F”);
grades
是一个数组列表


有什么方法可以将逻辑全部合并到一个流语句中吗?我试着让他们互相跟踪,但总是出现语法错误。我错过了什么?我试图查看IntStream和Stream的文档,但实际上找不到我要查找的内容。

您可以在
forEach
语句中添加这些条件,如

grades.stream()
.mapToInt(Integer::intValue)
.forEach(x -> {
    if (x >= 90) 
        System.out.println(x + " -> A");
    else if (x >= 80) 
        System.out.println(x + " -> B");
    else if (x >= 70)
        System.out.println(x + " -> C");
    ......
    // other conditions
});
更容易阅读,运行速度更快。
ps.“E”等级如何?

只需创建一个单独的函数来映射等级字母,并在单个流中调用:

static char gradeLetter(int grade) {
    if (grade >= 90) return 'A';
    else if (grade >= 80) return 'B';
    else if (grade >= 70) return 'C';
    else if (grade >= 60) return 'D';
    else return 'F';
}

grades.stream()
      .mapToInt(Integer::intValue)
      .filter(x -> x >= 50)
      .forEach(x -> System.out.println(x + " -> " + gradeLetter(x)));
如果您特别注重按等级对结果进行排序,可以在流的开头添加排序:

.sorted(Comparator.comparing(x -> gradeLetter(x)))

如果您愿意使用第三方库,此解决方案将与Java流和

我对列表和Eclipse集合使用了Java9工厂方法。如果其他情况都不匹配,则传递给构造函数的lambda将是默认情况

数字范围还可以由的实例表示,可以使用contains作为方法引用对其进行测试。以下解决方案将在Java10中使用局部变量类型推断

var mapGradeToLetter = new IntCaseFunction<>(x -> x + " -> F")
        .addCase(x -> x >= 90, x -> x + " -> A")
        .addCase(IntInterval.fromTo(80, 89)::contains, x -> x + " -> B")
        .addCase(IntInterval.fromTo(70, 79)::contains, x -> x + " -> C")
        .addCase(IntInterval.fromTo(60, 69)::contains, x -> x + " -> D")
        .addCase(IntInterval.fromTo(50, 59)::contains, x -> x + " -> F");

var grades = List.of(0, 40, 51, 61, 71, 81, 91, 100);
grades.stream()
        .mapToInt(Integer::intValue)
        .mapToObj(mapGradeToLetter)
        .forEach(System.out::println);
我在这里使用的是该对的
toString()
实现,因此以下是输出

0:F
40:F
51:F
61:D
71:C
81:B
91:A
100:A
可以在forEach中使用该对中包含的数字等级和字母等级定制输出


注意:我是Eclipse集合的提交者

这里有一个没有开关/if,else的解决方案

它在各种条件和动作之间有映射(打印逻辑)

Map actions=newlinkedhashmap();
//当心列表中的空值-取消装箱时可能会导致NullPointerException
actions.put(x->x>=90,x->System.out.println(x+“->A”);
actions.put(x->x>=80&&x System.out.println(x+“->B”);
actions.put(x->x>=70&&x System.out.println(x+“->C”);
actions.put(x->x>=60&&x System.out.println(x+“->D”);
actions.put(x->x>=50&&x System.out.println(x+“->F”);
grades.forEach(x->actions.entrySet().stream())
.filter(entry->entry.getKey().apply(x))
.findFirst()
.ifPresent(entry->entry.getValue().accept(x));
注:

  • 与传统的开关/if相比,它并不优雅
  • 对于每个等级,它可能会通过地图中的每个条目(这不是一个大问题,因为地图只有几个映射),但效率并不高
  • 小结:我更愿意使用switch/if,else继续使用您的原始代码。

    如果您所追求的是“分叉”流,则无法将其“分叉”为多个流。如果您希望在流操作中写入所有逻辑,那么您目前编写它的方式是最好的

    我认为在这里最简单的事情就是编写正常生成字符串的逻辑。如果您想对它感兴趣,可以使用
    mapToObj
    ,如下所示:

        grades.stream()
            .mapToInt(Integer::intValue)
            .mapToObj(x -> {
                if (x >= 90) {
                    return "A";
                }
                //etc
            })
            .forEach(System.out::println);
    

    您需要分离将标记转换为等级(int->String)和循环遍历arraylist的逻辑

    使用流作为循环数据的机制和转换逻辑的方法

    下面是一个简单的例子

    private static void getGradeByMarks(Integer marks) {
        if(marks > 100 || marks < 0) {
            System.err.println("Invalid value " + marks);
            return;
        }
        // whatever the logic for your mapping is
        switch(marks/10) {
            case 9:
                System.out.println(marks + " --> " + "A");
                break;
            case 8:
                System.out.println(marks + " --> " + "B");
                break;
            case 7:
                System.out.println(marks + " --> " + "C");
                break;
            case 6:
                System.out.println(marks + " --> " + "D");
                break;
            default:
                System.out.println(marks + " --> " + "F");
                break;
        }
    }
    
    public static void main(String[] args) {
        List<Integer> grades = Arrays.asList(90,45,56,12,54,88,-6);
    
        grades.forEach(GradesStream::getGradeByMarks);
    
    }
    
    private static void getGradeByMarks(整数标记){
    如果(标记>100 | |标记<0){
    System.err.println(“无效值”+标记);
    返回;
    }
    //不管映射的逻辑是什么
    开关(标记/10){
    案例9:
    System.out.println(标记+“-->”+“A”);
    打破
    案例8:
    System.out.println(标记+“-->”+“B”);
    打破
    案例7:
    System.out.println(标记+“-->”+“C”);
    打破
    案例6:
    System.out.println(标记+“-->”+“D”);
    打破
    违约:
    System.out.println(标记+“-->”+“F”);
    打破
    }
    }
    公共静态void main(字符串[]args){
    列表等级=数组。asList(90,45,56,12,54,88,-6);
    grades.forEach(GradesStream::getGradeByMarks);
    }
    
    以下代码生成的输出与原始代码完全相同,即顺序相同

    grades.stream()
      .filter(x -> x >= 50)
      .collect(Collectors.groupingBy(x -> x<60? 'F': 'E'+5-Math.min(9, x/10)))
      .entrySet().stream()
      .sorted(Map.Entry.comparingByKey())
      .flatMap(e -> e.getValue().stream().map(i -> String.format("%d -> %c", i, e.getKey())))
      .forEach(System.out::println);
    
    grades.stream()
    .过滤器(x->x>=50)
    .collect(收集器.groupingBy(x->x e.getValue().stream().map(i->String.format(“%d->%c”,即getKey()))
    .forEach(System.out::println);
    
    如果不需要该顺序,可以省略分组和排序步骤:

    grades.stream()
      .filter(x -> x >= 50)
      .map(x -> String.format("%d -> %c", x, x<60? 'F': 'E'+5-Math.min(9, x/10)))
      .forEach(System.out::println);
    
    grades.stream()
    .过滤器(x->x>=50)
    .map(x->String.format(“%d->%c”,x,x>=50)
    .forEach(x->System.out.printf(“%d->%c%n”,x,x{
    
    如果(x>=50)System.out.printf(“%d->%c%n”,x,xLambda)与否,无论在可读性和可用性方面,好的旧开关肯定是更好的方法
    Map<Predicate<Integer>, Consumer<Integer>> actions = new LinkedHashMap<>();
    //Beware of nulls in your list - It can result in a NullPointerException when unboxing
    actions.put(x -> x >= 90, x -> System.out.println(x + " -> A"));
    actions.put(x -> x >= 80 && x <= 89, x -> System.out.println(x + " -> B"));
    actions.put(x -> x >= 70 && x <= 79, x -> System.out.println(x + " -> C"));
    actions.put(x -> x >= 60 && x <= 69, x -> System.out.println(x + " -> D"));
    actions.put(x -> x >= 50 && x <= 59, x -> System.out.println(x + " -> F"));
    
    
    grades.forEach(x -> actions.entrySet().stream()
                        .filter(entry -> entry.getKey().apply(x))
                        .findFirst()
                        .ifPresent(entry -> entry.getValue().accept(x)));
    
        grades.stream()
            .mapToInt(Integer::intValue)
            .mapToObj(x -> {
                if (x >= 90) {
                    return "A";
                }
                //etc
            })
            .forEach(System.out::println);
    
    private static void getGradeByMarks(Integer marks) {
        if(marks > 100 || marks < 0) {
            System.err.println("Invalid value " + marks);
            return;
        }
        // whatever the logic for your mapping is
        switch(marks/10) {
            case 9:
                System.out.println(marks + " --> " + "A");
                break;
            case 8:
                System.out.println(marks + " --> " + "B");
                break;
            case 7:
                System.out.println(marks + " --> " + "C");
                break;
            case 6:
                System.out.println(marks + " --> " + "D");
                break;
            default:
                System.out.println(marks + " --> " + "F");
                break;
        }
    }
    
    public static void main(String[] args) {
        List<Integer> grades = Arrays.asList(90,45,56,12,54,88,-6);
    
        grades.forEach(GradesStream::getGradeByMarks);
    
    }
    
    grades.stream()
      .filter(x -> x >= 50)
      .collect(Collectors.groupingBy(x -> x<60? 'F': 'E'+5-Math.min(9, x/10)))
      .entrySet().stream()
      .sorted(Map.Entry.comparingByKey())
      .flatMap(e -> e.getValue().stream().map(i -> String.format("%d -> %c", i, e.getKey())))
      .forEach(System.out::println);
    
    grades.stream()
      .filter(x -> x >= 50)
      .map(x -> String.format("%d -> %c", x, x<60? 'F': 'E'+5-Math.min(9, x/10)))
      .forEach(System.out::println);
    
    grades.stream()
      .filter(x -> x >= 50)
      .forEach(x -> System.out.printf("%d -> %c%n", x, x<60? 'F': 'E'+5-Math.min(9, x/10)));
    
    grades.forEach(x -> {
       if(x >= 50) System.out.printf("%d -> %c%n", x, x<60? 'F': 'E'+5-Math.min(9, x/10));
    });