Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/334.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 避免多层次的循环嵌套_Java - Fatal编程技术网

Java 避免多层次的循环嵌套

Java 避免多层次的循环嵌套,java,Java,我有一个对象图,它是这样的: root : childs (array) : childs (array) // code for root // loop through direct root childs for (Child child : childs) { // Loop through the childs of the object in current context. for (AnotherChild anotherChild

我有一个对象图,它是这样的:

root
    : childs (array)
        : childs (array)
// code for root

// loop through direct root childs
for (Child child : childs) {

    // Loop through the childs of the object in current context.
    for (AnotherChild anotherChild : moreChilds) {

    }
}
我正以此构建一个JSON响应,因此我需要在每个集合中循环创建如下代码:

root
    : childs (array)
        : childs (array)
// code for root

// loop through direct root childs
for (Child child : childs) {

    // Loop through the childs of the object in current context.
    for (AnotherChild anotherChild : moreChilds) {

    }
}

如何避免此类代码?它最终将是一支箭。我本可以为for循环的每个级别创建自己的方法,但这是一个好方法吗?还有其他更好的方法吗?

我认为您有一个令人讨厌的设计问题,因为执行所有这些循环的类都知道很多其他类,因此破坏了设计

我从一些经验丰富的开发人员那里学到的一种方法是在他们自己的类中封装集合或数组;然后创建在执行一个操作的数组/集合上迭代的方法。在本例中,它可以调用包装集合的另一个类中的另一个方法

通过这种方式,每个类对其他类的功能或子对象的内部结构知之甚少

编辑 这里有一个例子。假设你在一个类似亚马逊的网站上有一个账户。在该帐户中,您关联了一些信用卡

因此,与其

class Account {
    List<CreditCard> creditCards;

    public CreditCard getPrimaryCard() {
        //complex code to find the primary credit card
    }
    //lots of other code related to the account and credit cards
}
你能行

class Account {
    CreditCards creditCards;

    public CreditCard getPrimaryCard() {
        creditCards.getPrimaryCard()
    }
    //lots of other code related to the account
}

class CreditCards {
    List<CreditCard> creditCards;

    public CreditCard getPrimaryCard() {
        //complex code to find the primary credit card
    }
    public void addCard(CreditCard creditCard) {
        //complex logic to validate that the card is not duplicated.
    }
    //lots of other code related to credit cards
}
通过这种方式,帐户不需要知道信用卡是如何存储在内存中的,它应该是一个列表吗?还是一套?还是从远程Web服务获取


请记住,这是一个简单的例子。

这是一个递归结构,那么您应该使用递归来处理嵌套。第一次深度探访就可以了

编辑到接口JSON对于递归访问伪代码示例,您将真正遵循@Mite Mitreski的建议:

void visit(Child tree) {
  json_write_class(tree);
  for (Attribute a : tree.attributes) {
    json_write_attr(a);
  if (tree.children != null) {
    json_push_indent();
    for (Child child : tree.children) {
      visit(child);
    }
    json_pop_indent();
  }
}
如果您需要更多的控制,您可以在该树的节点上编写某种“语义操作”来建立属性,并实现访问者模式来输出比第一个选项更详细的数据


使用语法和语法树的类比通常会有所帮助,这是我们作为程序员所习惯的最明显的示例。

如果我们讨论的是构建JSON响应这一特定问题,您可以使用某种序列化程序,如或编写自定义的序列化程序。在这个话题上有一个相关的问题

另一方面,对于某些其他用途,您可以使用更实用的方法,如或


但当涉及到大O复杂度时,这些并没有多大帮助,所以如果可能的话,你可能想尝试不同的方法

您可以提供所有感兴趣的类都应该实现的接口。该接口应提供将当前对象转换为JSON的方法。见示例:

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class JsonProgram {

    public static void main(String[] args) {
        Root root = new Root(Arrays.asList(new Child(Arrays.asList(
                new AnotherChild(1), new AnotherChild(2)))));
        System.out.println(root.toJSON());
    }

}

interface JsonState {
    String toJSON();
}

class Root implements JsonState {

    private List<Child> childs = new ArrayList<Child>();

    public Root(List<Child> childs) {
        this.childs = childs;
    }

    @Override
    public String toJSON() {
        StringBuilder builder = new StringBuilder();
        builder.append("{").append("\"childs\"").append(":[");
        int index = 0;
        for (Child child : childs) {
            builder.append(child.toJSON());
            if (index < childs.size() - 1) {
                builder.append(",");
            }
            index++;
        }
        builder.append("]\"}");
        return builder.toString();
    }
}

class Child implements JsonState {

    private List<AnotherChild> anotherChilds = new ArrayList<AnotherChild>();

    public Child(List<AnotherChild> anotherChilds) {
        this.anotherChilds = anotherChilds;
    }

    @Override
    public String toJSON() {
        StringBuilder builder = new StringBuilder();
        builder.append("{").append("\"anotherChilds\"").append(":[");
        int index = 0;
        for (AnotherChild child : anotherChilds) {
            builder.append(child.toJSON());
            if (index < anotherChilds.size() - 1) {
                builder.append(",");
            }
            index++;
        }
        builder.append("]}");
        return builder.toString();
    }
}

class AnotherChild implements JsonState {

    private int value;

    public AnotherChild(int value) {
        this.value = value;
    }

    @Override
    public String toJSON() {
        StringBuilder builder = new StringBuilder();
        builder.append("{").append("\"value\"").append(":\"").append(value)
                .append("\"}");
        return builder.toString();
    }
}
但这不是一个好的解决方案。您不应该实现自己的解决方案,而应该使用一些可以为您实现的库。我向你推荐。对我来说是最好的

编辑-GSON示例


上面的示例创建相同的输出。对我来说,这是一个更优雅的解决方案。

这段代码有什么问题?在这种情况下,嵌套循环在性能方面似乎是合理的,更重要的是,它是一个清晰而直接的实现。回答你的问题意味着试图猜测你不喜欢这个解决方案中的什么。你能提供一个例子吗?你能提供一个例子吗?但我想知道我自己如何处理这些问题。@user626912,如我所写,基本上,您可以使用功能性更强的方法来避免这种嵌套并使事情更清楚,但另一方面,通常数据的建模是个问题。在您的特定情况下,数据看起来正常,我将使用JSON序列化程序