Assuming Java 8 (when the streams have been introduced), it becomes quite easy if we can simplify the Letter constructor a bit and take a tiny assumption - the i variable in your code is simply the index of the letter - in this case, you can calculate it without passing it to the constructor (c - 'a'), therefore I'll omit it in my constructor - it adds a lot of unnecessasry noise.
To make my answer more complete, let's assume that this is the Letter class we'll be using:
public class Letter {
char c; int index;
public Letter(int c) {
this.c = (char) c;
this.index = c - 'a';
}
}
The entire thing can be accomplished within an oneliner:
List<Letter> l = "abcdefghijklmnopqrstuvwxyz".chars().mapToObj(Letter::new).collect(Collectors.toList());
The commented code looks like:
"abcdefghijklmnopqrstuvwxyz" // Take the alphabet string
.chars() // Turn the string into IntStream
.mapToObj(Letter::new) // Map all the characters into Letter constructor,
// effectively transposing into stream of Letters
.collect(Collectors.toList()); // Finally, collect all the Letters from the stream
// into a list.
alternatively, if you'd like to get an array instead, you can use .toArray(); instead of .collect(...);