Well basically you should reduce the work for the garbage collector. There a certain 'patterns' which produce a lot of work.
- Avoid having many objects with finalizers. Finalizers impose additional work on the garbage collector, because a object with a finalizer has to be collected twice.
- Avoid the 'midlife'-crisis. The .NET GC (on the desktop) is generational GC. When the object survive the first collection, but 'die' shortly after, the GC has done a lot of work for nothing. (coping to the second generation, collecting again, etc). So try to optimize the life-time of you objects in a way that they either die very quickly, or survive for a long, long time.
- Reduce unnecessary allocations. For example by using value type wisely. Or doing the work in a less memory-intensive way.
So in your case I guess that you either you've a 'midlife'-crisis with the short lived lists. Or you simple allocate list like mad.
In the first case: Try to make the life-span of the lists shorter. I can't tell you how the solution looks like for your application.
In the second case: Try to avoid allocation so many lists. Maybe you can use proper value-types? Or fixed sized arrays? Or change the structure of the code in such a way that less lists are needed?
Anyway, I would recommend to profile you applicaition and look how much you memory you allocate and how much can be collected in the first generation.