Per the docs on the setDataValue() method:
"Setting a field's value with this method makes it behave as if it were set by the user (with the exception of validation). The value is copied from the specified newValue, the value is rendered in the UI including any formatting, any dependent fields are recalculated, any Data Links are performed, and finally a "change" event is fired to all listeners."
So it does a lot more, but you are restricted to working only with the currently active value. If you imagine a list of 50 records, there is only 1 field but 50 DataValue objects for that field (one for each record). If the user is on a particular record (already clicked in it) and you are modifying a single value, this method would work too. However, if you needed to modify (for example) 20 records you would be better off searching throw the rows and modifying the DataValue objects you wanted, then calling a single myRecordObject.redisplay() to re-render everything correctly (including dependent field calculations and a lot more).
In your case of a Virtual Field outside of a record, either would work as there is a 1:1 correspondence between the Field object and the DataValue object.