将 for 循环转换为 forEach Lambda

Convert for loop to forEach Lambda

我正在学习 Lambda,但在转换时遇到了一点困难。我需要引入一个列表,使用 class 数组的 asList 方法将字段 class 的值方法提供的数组复制到该列表中。然后,我需要将 for 循环转换为使用 lambda 表达式作为其参数的 forEach 内部循环。 lambda 表达式的主体将是 for 循环的当前主体的代码。我相信我的 List 语法正确( List list = Arrays.asList(data); ),但我很难弄清楚如何处理 for 循环,甚至不知道从哪里开始。任何指导将不胜感激。谢谢

public AreaData(String... data)
{
    List<String> list = Arrays.asList(data);


    /* Assert to check that the data is of the expected number of items. */
    assert data.length == Field.values().length : "Incorrect number of fields";

    for( Field field : Field.values() )
    {
        int width;
        String formatString;
        if( field == NAME )
        {
            /* Get the name value and store it away. */
            String value = data[field.position()];
            strings.put(field, value);
            /* Get the needed width of the field to hold the name. */
            width = max(value.length(), field.getFieldHeading().length());
            formatString = "s";
        } else
        {
            /* If the value is of the wrong form, allow the NumberFormatException
               to be thrown. */
            Double value = Double.parseDouble(data[field.position()]);
            /* Assertion to check value given is positive.  */
            assert value.compareTo(0.0) >= 0 :
                    "invalid " + field.name() + " value=" + value.toString();
            /* Get the field value and store it away. */
            doubles.put(field, value);
            /* Get needed width of the field to hold the heading or value. */
            width = max((int) log10(value) + MINIMUM,
                    field.getFieldHeading().length() + HEADING_SEPARATION);
            formatString = ".2f";
        }
        /* Keep the widest value seen, and record the corresponding format. */
        if( width > WIDTHS.get(field) )
        {
            WIDTHS.put(field, width);
            FORMATS.put(field, "%" + width + formatString);
        }
    }
    /* Optimization: to avoid doing this every time a comparison is made. */
    this.nameCaseless = strings.get(NAME).toUpperCase().toLowerCase();
}

Stream.of(Field.values()).forEach() 应该可以解决问题:

public AreaData (String... data) {
        List<String> list = Arrays.asList(data);
        /* Assert to check that the data is of the expected number of items. */
        assert data.length == Field.values().length : "Incorrect number of fields";
        int width;
        String formatString;
        Stream.of(Field.values()).forEach(
                field -> {
                    if (field == NAME) {
                        /* Get the name value and store it away. */
                        String value = data[field.position()];
                        strings.put(field, value);
                        /* Get the needed width of the field to hold the name. */
                        width = max(value.length(), field.getFieldHeading().length());
                        formatString = "s";
                    } else {
                        /* If the value is of the wrong form, allow the NumberFormatException
                           to be thrown. */
                        Double value = Double.parseDouble(data[field.position()]);
                        /* Assertion to check value given is positive.  */
                        assert value.compareTo(0.0) >= 0 :
                                "invalid " + field.name() + " value=" + value.toString();
                        /* Get the field value and store it away. */
                        doubles.put(field, value);
                        /* Get needed width of the field to hold the heading or value. */
                        width = max((int) log10(value) + MINIMUM,
                                field.getFieldHeading().length() + HEADING_SEPARATION);
                        formatString = ".2f";
                    }
                    /* Keep the widest value seen, and record the corresponding format. */
                    if (width > WIDTHS.get(field)) {
                        WIDTHS.put(field, width);
                        FORMATS.put(field, "%" + width + formatString);
                    }
                });

        /* Optimization: to avoid doing this every time a comparison is made. */
        this.nameCaseless = strings.get(NAME).toUpperCase().toLowerCase();
    }

也就是说,您应该考虑以下经验法则:

A lambda expression should be ideally up to 3 lines of code and in no case more than 5 lines!

如果您特别想将其转换为使用流和 lambda,那么我觉得您也应该借此机会根据这些工具的意图对其进行重构。这意味着使用过滤器、收集器等,而不是仅仅将所有代码转换为单个 lambda。

例如:

Arrays.stream(Field.values())
    .peek(field -> field.storeValue(data))
    .filter(field -> field.getWidth(data) > widths.get(field))
    .forEach(field -> storeWidthAndFormat(data, widths, formats));

这假设您将与 NAME 关联的逻辑封装在 Field 枚举中(这是我推荐的)。