There is no single answer - design is about juggling priorities, tradeoffs and comprimises, to arrive at something that works well in your sitluation. I'll briefly cover the relative merits and drawbacks of using functors, accessors and full encapsulation.
Functors
Using functors can be convenient, and avoids boilerplate iteration. This also allows you to cleanly separate what you are executing for each item in the list from when you execute it. With a for-each loop, the two are most often coupled together. Where functors don't work is if you need to perform an operation on multiple lists, either from the same object, or from multiple objects, or if you only need a few elements of the list. Use of functors constrains execution order - items must be used in the order iterated by the provider. The functor has no control. This can be a blessing, and also a curse.
The example of Person, scheduling preferences and a Scheduler, the scheduler could provide an external iterator for possible schedule times:
schedules = scheduler.schedules(person.getSchedulePreferred())
The getSchedulePreferred() returns a predicate that selects the schedules from all those available that are preferred by the given person.
Iterating across all schedules may not be the most efficient way of implementing this. Say, if the person only wants schedules in June, then all schedules for the rest of the year will be wastefully iterated.
Accessors
Making the lists available via gtters can be beneficial when implementing functionality that is not intrinsic to the class. For example, given two Orders, find the items that they have in common. This simple to implement if the lists are provided as getters for external traversal, and very simple if the lists are provide in some known order (e.g. if the Order has a getSortedItems()
method.) The complexity here is managing mutability of the list, although many languages have direct support to disable mutation (e.g. const in C++) or wrapping the list in an immutable wrapper.
For the example, the person could expose the list of schedule preferences, which are then used directly by the scheduler. The scheduler has the opportunity to be "smart" about how the preferences are applied, e.g. it could build a query to a datbase to fetch matching schedules based on the persons preferences.
Encpasulation
The third alternative is to question if external access is required. It's one symptom of an anemic domain model that objects are all properties and no behaviour. But don't strive to put behaviour in a domain object just to avoid this anti-pattern - the behavior should be a natural part of that object's responsibility.
I don't think this applies here - person, scheduler and scheduling preference clearly fulfill different roles and have clear responsibilities. Adding a method on one entity that tries to compute data from another would be an unnecessary tight coupling.
Summary
In this particular case, my preference is for the getter, since it allows the scheduler more control over how the schedule preferences are used, rather than being "force-fed" them through a functor.