If you inspected the source code of the map and where functions, you probably noticed that the return type of these functions is not a List, but another type called Iterable. This abstract class represents an intermediary state before you decide what concrete data type you want to store. It doesn't necessarily have to be a List. You can also convert your iterable into a Set if you want.
The advantage of using iterables is that they are lazy. Programming is one of the only professions where laziness is a virtue. In this context, laziness means that the function will only be executed when it's needed, not earlier. This means that we can take multiple higher-order functions and chain them together, without stressing the processor with unnecessary cycles.
We could reduce the sample code even further and add more functions for good measure:
final names = data
.map<Name>((raw) => Name(raw['first'], raw['last']))
.where((name) => name.last.startsWith('M'))
.where((name) => name.first.length > 5)
.toList(growable: false);
Each of these functions is cached in our Iterable and only runs when you make the call to toList(). Here, you are serializing the data in a model, checking whether the last name starts with M, and then checking whether the first name is longer than five letters. This is executed in a single iteration through the list!