1 // Copyright (C) 2002-2003 Jon A. Maxwell (JAM)
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
16 
17 package net.sourceforge.jnlp.util;
18 
19 import java.lang.ref.*;
20 import java.util.*;
21 
22 /**
23  * This list stores objects automatically using weak references.
24  * Objects are added and removed from the list as normal, but may
25  * turn to null at any point (ie, indexOf(x) followed by get(x)
26  * may return null).  The weak references are only removed when
27  * the trimToSize method is called so that the indices remain
28  * constant otherwise.
29  *
30  * @author <a href="mailto:jmaxwell@users.sourceforge.net">Jon A. Maxwell (JAM)</a> - initial author
31  * @version $Revision: 1.3 $
32  * @param <E> generic typeto be used in this list
33  */
34 public class WeakList<E> extends AbstractList<E> {
35 
36     /* list of weak references */
37     private final ArrayList<WeakReference<E>> refs = new ArrayList<>();
38 
39     /**
40      * Create a weak random-access list.
41      */
WeakList()42     public WeakList() {
43     }
44 
45     /**
46      * Extract the hard reference out of a weak reference.
47      */
deref(WeakReference<E> o)48     private E deref(WeakReference<E> o) {
49         if (o != null)
50             return o.get();
51         else
52             return null;
53     }
54 
55     /**
56      * @param index of field to get
57      * @return the object at the specified index, or null if the
58      * object has been collected.
59      */
60     @Override
get(int index)61     public E get(int index) {
62         return deref(refs.get(index));
63     }
64 
65     /**
66      * @return the size of the list, including already collected
67      * objects.
68      */
69     @Override
size()70     public int size() {
71         return refs.size();
72     }
73 
74     /**
75      * Sets the object at the specified position and returns the
76      * previous object at that position or null if it was already
77      * collected.
78      * @param index position where to place element
79      * @param element data which to put on position
80      * @return previous object on that position
81      */
82     @Override
set(int index, E element)83     public E set(int index, E element) {
84         return deref(refs.set(index, new WeakReference<>(element)));
85     }
86 
87     /**
88      * Inserts the object at the specified position in the list.
89      * Automatically creates a weak reference to the object.
90      * @param index position where to insert element
91      * @param element data which to put on position
92      */
93     @Override
add(int index, E element)94     public void add(int index, E element) {
95         refs.add(index, new WeakReference<>(element));
96     }
97 
98     /**
99      * Removes the object at the specified position and returns it
100      * or returns null if it was already collected.
101      * @param index of element to be removed
102      * @return previous object on that position
103      */
104     @Override
remove(int index)105     public E remove(int index) {
106         return deref(refs.remove(index));
107     }
108 
109     /**
110      * @return a list of hard references to the objects.  The
111      * returned list does not include the collected elements, so its
112      * indices do not necessarily correlate with those of this list.
113      */
hardList()114     public List<E> hardList() {
115         List<E> result = new ArrayList<>();
116 
117         for (int i = 0; i < size(); i++) {
118             E tmp = get(i);
119 
120             if (tmp != null)
121                 result.add(tmp);
122         }
123 
124         return result;
125     }
126 
127     /**
128      * Compacts the list by removing references to collected
129      * objects.
130      */
trimToSize()131     public void trimToSize() {
132         for (int i = size(); i-- > 0;)
133             if (get(i) == null)
134                 remove(i);
135     }
136 
137 }
138