In these types of situations, there are three common solutions:
(1) If you know that the individual elements have clone() methods that work as you intend, create a new array and fill it with the clone() of each corresponding element. As a rule of thumb, "basic" objects from JDK such as Strings, number representations etc should be fine. A disadvantage of clone() is that it's a bit of a 'loose cannon': you don't know a priori exactly how deep the 'clone' will be if the method has been overridden for a particular class and what references might potentially get re-used or not. It also has a particular danger that subclasses of cloneable objects which rely on logic in their constructor are liable not to work. But as I say, simple JDK objects should be fine.
(2) Serialise the list to an ObjectOutputStream wrapped around a ByteArrayOutputStream. Then take the resulting byte array, and wrap a ByteArrayInputStream and ObjectInputStream around it and read in from it a new, deep copy of the list.
(3) In an ideal world, create a new list, filling it with explicitly created "copies" of the objects in question. Where it's not too cumbersome to code, this is the ideal solution because you 'know what's actually going on': there'll be no hidden surprises in terms of objects accidentally re-referenced rather than re-created because e.g. a clone() method didn't work as you expected.
As you have a simple container object (an array list) whose structure you can easily re-create, then (2) may be overkill. It can be handy for re-creating more complex structures.
Re (1), you should be particularly suspicious of cloning objects from third party libraries where the objects weren't specifically designed with clone() in mind. The problem is that it's easy for people to either subclass a JDK (cloneable) class or else a token clone() method without actually thinking about it in detail-- in my experience, clone() has some subtleties that many developers aren't aware of (e.g. that the constructor doesn't get called on the new object) which can lead to unanticipated problems. So if you can't actually see reliable source code to be sure that clone() will be safe, I would avoid it.