为了账号安全,请及时绑定邮箱和手机立即绑定

将 Java final 关键字添加到在循环内构建实例的工作方法

将 Java final 关键字添加到在循环内构建实例的工作方法

30秒到达战场 2022-03-10 21:57:19
采取以下 POJO:public class Widget {    private String fizz;    private Long buzz;    private List<Fidget> collaborators;   // Constructor, getters & setters}public class Fidget {    private String fizz;    private String foo;    // Constructor, getters & setters}以及以下(工作)方法:public void compriseWidgets(List<Fidget> fidgetList) {    List<Widget> widgets = new ArrayList<Widget>();    Widget currentWidget = null;    for (Fidget fidget : fidgetList) {        if (currentWidget == null ||                 !currentWidget.getFizz().equals(fidget.getFizz())) {            currentWidget = new Widget();            widgets.add(currentWidget);            currentWidget.setFizz(fidget.getFizz());            currentWidget.setBuzz(fidget.getFoo().length());        }        currentWidget.getCollaborators().add(fidget);    }    return widgets;}在这里,我们只想返回一个List<Widget>并填充该列表:从Fidget输入列表中的第一个开始(因此currentWidget == null);和如果Fidget和currentWidget具有相同的fizz值collaborators此外,currentWidget无论 fizzes 是否匹配,我们都希望继续追加。我的问题一个新的代码风格准则要求我们声明所有变量final...意味着我需要将上面的代码重构为如下所示:public void compriseWidgets(final List<Fidget> fidgetList) {    final List<Widget> widgets = new ArrayList<Widget>();    final Widget currentWidget = null;    for (final Fidget fidget : fidgetList) {        ...    }    return widgets;}因为它既需要在循环Widget 内创建一个新的,又需要一个外部(循环外)对Widget我们可以添加的 a 的引用collaborators,所以我完全不知道如何用final. 有任何想法吗?另外,请注意,这不是我可以“推后”的,我只需要弄清楚它并让它与新的编码标准一起使用。
查看完整描述

2 回答

?
慕码人2483693

TA贡献1860条经验 获得超9个赞

为了扩展我的评论,您可以或多或少地机械地转换您的示例代码,如下所示:


public List<Widget> compriseWidgets(final List<Fidget> fidgetList) {

    final List<Widget> widgets = new ArrayList<Widget>();

    final Widget[] currentWidget = new Widget[] {null};


    for (final Fidget fidget : fidgetList) {

        if (currentWidget[0] == null || 

                !currentWidget[0].getFizz().equals(fidget.getFizz())) {


            currentWidget[0] = new Widget();

            widgets.add(currentWidget);

            currentWidget.setFizz(fidget.getFizz());

            currentWidget.setBuzz(fidget.getFoo().length());

        }


        currentWidget.getCollaborators().add(fidget);

    }


    return widgets;

}

许多变量可以在final没有任何特殊影响的情况下生成,包括 Fidgets 和 Widgets 的列表,以及增强for循环中的循环变量。原始方法中唯一的其他变量是currentWidget,实现对其进行了修改。这可以用final长度为 1 的 ( ) 数组替换,然后可以将其第零个元素用作原始变量的直接替换。


一个更麻烦的要求是您不能使用赋值语句(变量声明中的初始化程序不被视为“赋值”)。这正在推动一种更具功能性的编程风格,我想这可能是您的新指南的意图。然后,您可以像这样处理它:


public List<Widget> compriseWidgets(final List<Fidget> fidgetList) {

    final List<Widget> widgets = new ArrayList<Widget>();

    final ListIterator<Fidget> fidgets = fidgetList.listIterator();


    while (addWidget(widgets, fidgets)) { /* empty */ }


    return widgets;

}    


private boolean addWidget(final List<Widget> widgets, final ListIterator<Fidget> fidgets) {

    if (fidgets.hasNext()) {

        final Fidget firstFidget = fidgets.next();

        final Widget currentWidget = new Widget();


        widgets.add(currentWidget);

        currentWidget.setFizz(firstFidget.getFizz());

        currentWidget.setBuzz(firstFidget.getFoo().length());

        currentWidget.getCollaborators().add(firstFidget);


        while (fidgets.hasNext()) {

            final nextFidget = fidgets.next();


            if (currentWidget.getFizz().equals(nextFidget.getFizz())) {

                currentWidget.getCollaborators().add(nextFidget);

            } else {

                fidgets.previous();

                return true;

            }

        }

    }


    return false;

}

这几乎是相同的技巧,只是不太明显。可变状态隐藏在调用堆栈(每次调用addWidget()代表原始方法的突变currentWidget())和容器对象中,这次是 a ListIterator。


人们可以在函数式编程方向上走得更远。例如,一般来说,您可以考虑基于流的方法,尽管我认为在这种特殊情况下,这并不是完全干净的。然而,更一般的函数式编程没有适用于 Streams 的约束。


查看完整回答
反对 回复 2022-03-10
?
白衣染霜花

TA贡献1796条经验 获得超10个赞

Builder 设计模式是构建不可变对象的好方法。来源: https ://stackoverflow.com/a/15461337/4245294


我喜欢这个设计模式的这个版本的地方在于它如何在创建对象之前为您提供验证规则的完美位置。


应用于此问题的示例:


public class Widget {

    private final String fizz;

    private final Long buzz;

    private final List<Fidget> collaborators;


    private Widget(Builder builder) {

        this.fizz = builder.fizz;

        this.buzz = builder.buzz;

        this.collaborators = builder.collaborators;

    }


    public static Builder builder() {

        return new Builder();

    }


    public static class Builder {

        private String fizz;

        private Long buzz;

        private List<Fidget> collaborators = new ArrayList<>();


        public Builder addFizz(String fizz) {

            this.fizz = fizz;

            return this;

        }


        public Builder addBuzz(Long buzz) {

            this.buzz = buzz;

            return this;

        }


        public Builder addCollaborators(List<Fidget> fidgets) {

            collaborators.addAll(fidgets);

            return this;

        }


        public Builder addCollaborator(Fidget fidget) {

            collaborators.add(fidget);

            return this;

        }


        private void validate() throws InvalidArgumentException{

            ArrayList<String> invalidArguments = new ArrayList<>();

            boolean failedValidation = false;

            if (collaborators.isEmpty()) {

                invalidArguments.add("collaborators");

                failedValidation = true;

            }

            if (this.fizz == null) {

                invalidArguments.add("fizz");

                failedValidation = true;

            }

            if (this.buzz == null) {

                invalidArguments.add("buzz");

                failedValidation = true;

            }

            if (failedValidation) {

                throw new InvalidArgumentException(invalidArguments.toArray(new String[0]));

            }

        }


        public Widget build() {

            validate();

            return new Widget(this);

        }

    }

}

然后您创建一个有效的 Widget 对象,如下所示:


Widget widget = Widget.builder().addFizz("test").addBuzz(999).addCollaborators(fidgets).build();

您的compriseWidget方法存在我在对问题的评论中提到的问题,否则我也会为此提供一个示例。


查看完整回答
反对 回复 2022-03-10
  • 2 回答
  • 0 关注
  • 192 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信