# Fill ArrayList of String with empty String to maintain order of elements

I'm writing a logic for converting data fetched from data base into CSV format. The total number of header fields in CSV file are 14. Now it is possible that not all the field values are available. To give an example the data could be :

__________________________________________
|C1 | C2 | C3 | C4 | C5 |....|C12|C13|C14|
------------------------------------------
| V | V  | V  | V  | V  | V  | V |   |   |
| V | V  | V  | V  | V  |    |   |   |   |
| V | V  | V  | V  | V  |    |   |   |   |


Now I use an ArrayList to store the data in order of CSV fields. Also the values for first five columns (C1-C5) and the column C12 of CSV file are always available . The values for C6-C11 may or may not be available and they are stored in another list.And this will always be the case.Now to maintain the order, I have to insert empty string in ArrayList. So the code would be like -

ArrayList<String> csvRow = new ArrayList<String>();
// adding mandatory values (C1-C5)
csvRow.add(value); // there will be 5 such statement.
if(!optionalValList.isEmpty()) {
// add the values to csvRow List for the C6-C11 fields
}else {
// do this for C6-C11 fields. So there
// will be 6 such statements to add the empty string to List to
// maintain the order of fields in CSV.

}


Note : Values C1-C5 and C12 are always available. And this will always be the case.

Now I don't like this approach. So I have come up with a logic using the lambda expression which will replace the logic in else block. It is as below :

 public List<String> createList(List<String> inputList){
return IntStream.range(0,14)
.mapToObj(i -> (i < inputList.size())? inputList.get(i):"")
.collect(Collectors.toList());
}


So the else block will be like :

else {
csvRow = createList(csvRow);
csvRow.set(11,value); // setting the column C12
}


Now I want get feedback on this approach. Is this abuse of the lambda features? If yes how can I do this better.

Have you considered that ArrayList could be a little overkill? If your list will always be a defined length, you could use a String[] to hold your data. That way, the default value is always null and you don't have to worry about IndexOutOfBoundsExceptions.

You can still use constructs like for(String value : csvRow) to access your data, and if you need the finesse of the Collections API, you can always use Arrays.asList(csvRow).

If you're looking for NullPointerException protection, you can run Arrays.fill(csvRow, "") first to ensure that all indexes return an empty string unless otherwise populated.

String tmp = "placeholder";

String[] csvRow = new String[14];
Arrays.fill(csvRow, "");
// Add values for C1-C5 (dummy data)
for(int i=0;i<5;i++) csvRow[i] = tmp;

// Add in optional values
List<String> optionalValues = Collections.emptyList();
if(!optionalValues.isEmpty()) {
int i = 6;
for(Iterator<String> ovI = optionalValues.iterator();
ovI.hasNext() && i < csvRow.length;i++){
csvRow[i] = ovI.next();
}
}
// Add C12 if not already present
if("".equals(csvRow[11])) csvRow[11] = tmp;


You don't need to work around the specifics of which columns will always be there and which won't. The database row you get back has some values and some nulls. For a value, you insert that value into your CSV row. For a null, you insert "". I haven't touched Java in a while, but what you want will look roughly like:

optionalValList.map { v -> v == null ? "" : v }.foreach { csvRow.add(v) }


Your createList method looks fine to me. There's only one thing to improve: the list returned by Collectors.toList does not guarantee anything. It might not be modifiable. Therefore you should use another collector, the one to which you can pass ArrayList::new as argument. (I forgot the exact method name.)