Generates a CSV output of dummy data
I want to know if these is a simple way to remove all of the nested for-loops and do this task more elegantly, whilst retaining simplicity.


Yes, for some definition of simplicity.  Consider 

public class DataCreator implements Iterable&lt;String&gt; {

    private final List&lt;List&lt;String&gt;&gt; parts;
    private final List&lt;String&gt; lines = new ArrayList&lt;&gt;();
    private final String SEPARATOR;

    private DataCreator(List&lt;List&lt;String&gt;&gt; parts, String separator) {
        this.parts = parts;
        this.SEPARATOR = separator;
    }

    private void joinParts(int index, String line) {
        if (index &gt;= parts.size()) {
            lines.add(line + lines.size());

            return;
        }

        for (String part : parts.get(index++)) {
            joinParts(index, line + part + SEPARATOR);
        }
    }

    @Override
    public Iterator&lt;String&gt; iterator() {
        return lines.iterator();
    }

    public static DataCreator create(List&lt;List&lt;String&gt;&gt; parts, String separator) {
        DataCreator creator = new DataCreator(parts, separator);

        creator.joinParts(0, new String());

        return creator;
    }

    public static void main(String[] args) {
        String[] timePeriods = 
            { 
            "2001-01-01", "2001-01-02", "2001-01-03", "2001-01-04", "2001-01-05", 
"2001-01-06", "2001-01-07", "2001-01-08", "2001-01-09", "2001-01-10", "2001-01-11", 
"2001-01-12", "2001-01-13", "2001-01-14", "2001-01-15", "2001-01-16", "2001-01-17", 
"2001-01-18", "2001-01-19", "2001-01-20", "2001-01-21", "2001-01-22", "2001-01-23", 
"2001-01-24", "2001-01-25", "2001-01-26", "2001-01-27", "2001-01-28", "2001-01-29", 
"2001-01-30", "2001-01-31",
            "2001-02-01", "2001-02-02", "2001-02-03", "2001-02-04", "2001-02-05", 
"2001-02-06", "2001-02-07", "2001-02-08", "2001-02-09", "2001-02-10", "2001-02-11", 
"2001-02-12", "2001-02-13", "2001-02-14", "2001-02-15", "2001-02-16", "2001-02-17", 
"2001-02-18", "2001-02-19", "2001-02-20", "2001-02-21", "2001-02-22", "2001-02-23", 
"2001-02-24", "2001-02-25", "2001-02-26", "2001-02-27", "2001-02-28",
            "2001-03-01", "2001-03-02", "2001-03-03", "2001-03-04", "2001-03-05", 
"2001-03-06", "2001-03-07", "2001-03-08", "2001-03-09", "2001-03-10", "2001-03-11", 
"2001-03-12", "2001-03-13", "2001-03-14", "2001-03-15", "2001-03-16", "2001-03-17", 
"2001-03-18", "2001-03-19", "2001-03-20", "2001-03-21", "2001-03-22", "2001-03-23", 
"2001-03-24", "2001-03-25", "2001-03-26", "2001-03-27", "2001-03-28", "2001-03-29", 
"2001-03-30", "2001-03-31"
            };

        List&lt;List&lt;String&gt;&gt; parts = new ArrayList&lt;&gt;();
        parts.add(Arrays.asList("DD1", "DD2", "DD3", "DD4"));
        parts.add(Arrays.asList("1A", "1B", "1C", "1D", "1E", "1F", "1G", "1H", 
                                "1J", "1K", "1L", "1M", "1N", "1O", "1P", "1Q"));
        parts.add(Arrays.asList("AB1", "ZZ2", "FAQWE1", "1234", "_Z"));
        parts.add(Arrays.asList("D"));
        parts.add(Arrays.asList(timePeriods));

        for (String line : DataCreator.create(parts, ", ")) {
            System.out.println(line);
        }
    }

}


This is slightly more complicated, but it uses it for making the code more generic and reusable.  

I used the factory method (create) because I don't like doing complicated work in the constructor.  This leaves the code more flexible for later modification.  

Advantages over the original:  


Easy to add or remove columns.  Just add or delete the appropriate parts.add line.  
Reusable.  Capable of doing things other than immediate display.  
Easy to use.  Because it implements Iterable, you can just throw it into a for loop and use it.
Divided into methods.  
Defines SEPARATOR at construction time rather than hardcoding it.  


Downsides retained include that you have to edit code to change the format of the strings.  For example, if you wanted the row number to be in the first column instead of the last, you would have to modify the code.  

I left main inside of DataCreator for simplicity's sake.  Best practices would suggest putting it in its own class so that DataCreator would be more reusable.  

A possible future improvement would be to generate the timePeriods with a method.  More complicated the first time that you write it, but easier to use in the future.