简体   繁体   English

使用 Java 流转换具有多个 if/else 的经典嵌套循环

[英]Convert classic nested loops with multiple if/else with Java streams

I need some guidance on what can be done here using Java Streams.我需要一些关于使用 Java Streams 可以在此处完成的操作的指导。 I have the 2D Arrray of test[][] object which holds row, col and value inside.我有 test[][] object 的二维数组,其中包含行、列和值。 in order to produce different representation, I loop through and manually append different characters to do that.为了产生不同的表示,我循环并手动 append 不同的字符来做到这一点。

public class Test{
    private Point[][] test;   // like a rectangle
    ...
}

public String someFunction() {
    StringBuilder result = new StringBuilder(150);
    for (int row = 0; r < 10; row++) {
        for (int col = 0; c < 15; col++) {
            if (test[row][col].getVal() == 1) {
                result.append('L');
            } else if (test[row][col].getVal() == 2) {
                result.append('M');
            } else if (test[row][col].getVal() == 10) {
                result.append('N');
            } else {
                result.append(' ');
            }
        }
        result.append('\n');
    }
    return result.toString();
 }

Also, Generally how does the streams work with 2 loops, some good examples would be great help.此外,通常流如何与 2 个循环一起工作,一些很好的例子会很有帮助。

To simplify a bit this code, you can use for-each loops, this way you won't need to handle indexes为了简化这段代码,您可以使用for-each循环,这样您就不需要处理索引

public String someFunction() {
    for (C[] row : test) {
        for (C item : row) {
            if (item.getVal() == 1) {
                result.append('L');
            } else if (item.getVal() == 2) {
                result.append('M');
            } else if (item.getVal() == 10) {
                result.append('N');
            } else {
                result.append(' ');
            }
        }
        result.append('\n');
    }
    return result.toString();
}

You won't win something by using the Stream version because you're doing easy thing just iterating an array so the classic loop is nice, but here it is使用 Stream 版本不会赢得任何东西,因为您正在做简单的事情,只是迭代一个数组,所以经典循环很好,但在这里

public static String someFunction() {
    return Arrays.stream(test)
            .map(row -> Arrays.stream(row).map(item -> {
                switch (item.getVal()) {
                    case 1:
                        return "L";
                    case 2:
                        return "M";
                    case 10:
                        return "N";
                    default:
                        return " ";
                }
            }).collect(Collectors.joining()))
            .collect(Collectors.joining("\n"));
}

And if you want to see it, the Stream version with the indices如果你想看的话,Stream 版本的索引

public String someFunction() {
    return IntStream.range(0, test.length).mapToObj(rowIdx -> IntStream.range(0, test[rowIdx].length).mapToObj(colIdx -> {
        switch (test[rowIdx][colIdx].getVal()) {
                    ...
        }
    }).collect(Collectors.joining())).collect(Collectors.joining("\n"));
}

my solution for the mapping of int to char is to use char array.我将 int 映射到 char 的解决方案是使用 char 数组。

char[] intToChar = {' ', 'L', 'M', ' ', ' ', ' ', ' ', ' ', ' ', ' ', 'N};

this can replace the series of if or switch with a simple assignment这可以用一个简单的赋值替换一系列ifswitch

this can be made simpler with a String and the method charAt(i)这可以通过 String 和方法charAt(i)变得更简单

Here's a slight variation of Azro's answer, since I'd basically already written it.这是 Azro 答案的一个细微变化,因为我基本上已经写过了。

If the indices are important (ie for some reason you want to perform the calculation only on a portion of the full "grid") then Arrays.stream has another signature where you can specify those, just as you did in your answer.如果索引很重要(即由于某种原因您只想对完整“网格”的一部分执行计算),那么Arrays.stream有另一个签名,您可以在其中指定这些,就像您在答案中所做的那样。

From Java 14, you can use switch expressions to make the conversion from point value to character a bit nicer.从 Java 14 开始,您可以使用 switch 表达式使从点值到字符的转换更好一点。

You can also also use StringBuilder s in a similar way as your iterative example.您还可以使用与迭代示例类似的方式使用StringBuilder Collectors.joining works in a similar way but it is not able to pre-allocate the right amount of space. Collectors.joining以类似的方式工作,但它无法预先分配适量的空间。 Almost certainly irrelevant for 150 characters, but I thought it made an interesting example anyway.几乎可以肯定与 150 个字符无关,但无论如何我认为这是一个有趣的例子。

return Arrays.stream(test, 0, 10)
    .map(row -> Arrays.stream(row, 0, 15)
        .map(ValueSource::getVal)
        .map(val -> switch(val) {
            case 1 ->  'L';
            case 2 ->  'M';
            case 10 -> 'N';
            default -> ' ';
        })
        .collect(Collector.of(() -> new StringBuilder(row.length), StringBuilder::append, StringBuilder::append))
    )
    .collect(Collector.of(() -> new StringBuilder(150), StringBuilder::append, StringBuilder::append, StringBuilder::toString));

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

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