How to avoid nested for each loop?

I have a class that needs to parse an XML file, for example:

<customers>
        ...
        <customer>
            <id>123456</id>
            <name>Mike</name>
            <orders>
                ...
                <order>
                    <id>233658</id>
                    <positions>
                        ...
                        <position>
                            <id>12345</id>
                            <price>10.0</price>
                            <count>5</count>
                        </position>
                        ...
                    </positions>
                </order>
                ...
            </orders>
        </customer>
<customers>

      

I'm going to decouple it from JAXB rather than process result objects to get statistics (like max order amount, total order amount, etc.)

Is it bad practice to use a three-level foreach loop in this case?

public void getStatistics() {
    for (Customer customer: this.customers.getCustomer()) {

        BigDecimal customerTotalAmount = new BigDecimal(0);
        for (Order order : customer.getOrders().getOrder()) {

            BigDecimal orderAmount = new BigDecimal(0);
            for (Position position : order.getPositions().getPosition()) {
                orderAmount = orderAmount.add( position.getPrice().multiply(new BigDecimal(position.getCount())) );
            }

            customerTotalAmount = customerTotalAmount.add(orderAmount);
            this.totalOrders++;
        }

        this.totalAmount = this.totalAmount.add(customerTotalAmount);
    }
}

      

The XSD schema automatically generates the Customer, Order and Position classes and I think it is not a good idea to change them.

What am I doing wrong? How can I avoid these nested loops?

Thank.

+3


source to share


1 answer


I would recommend to extract some methods:

public void getStatistics() {
    for (Customer customer: this.customers.getCustomer()) {
        BigDecimal customerTotalAmount = processCustomer(customer);
        this.totalAmount = this.totalAmount.add(customerTotalAmount);
    }
}

private void processCustomer(Customer customer){
    BigDecimal customerTotalAmount = new BigDecimal(0);
    for (Order order : customer.getOrders().getOrder()) {
        BigDecimal orderAmount = new BigDecimal(0);
        for (Position position : order.getPositions().getPosition()) {
            orderAmount = orderAmount.add( position.getPrice().multiply(new BigDecimal(position.getCount())) );
        }

        customerTotalAmount = customerTotalAmount.add(orderAmount);
        this.totalOrders++;
    }
    return customerTotalAmount;
}

      



Do the same for the Order and Position loop, give descriptive descriptions of the methods, and make sure they return the correct values, and you end up with nice, clean code. These are still nested loops, but at least your eyes don't hurt when you see them.

+4


source







All Articles