RobotCore 1.0
WPILib port to raspberry Pi
Loading...
Searching...
No Matches
WeakLinkedHashSet.java
1// Copyright (c) FIRST and other WPILib contributors.
2// Open Source Software; you can modify and/or share it under the terms of
3// the WPILib BSD license file in the root directory of this project.
4
5package org.wpilib.util.container;
6
7import static org.wpilib.util.ErrorMessages.requireNonNullParam;
8
9import java.lang.ref.WeakReference;
10import java.util.AbstractSet;
11import java.util.ArrayList;
12import java.util.Collection;
13import java.util.Iterator;
14import java.util.LinkedHashMap;
15import java.util.NoSuchElementException;
16import java.util.SequencedSet;
17import java.util.Spliterator;
18import java.util.Spliterators;
19
30public final class WeakLinkedHashSet<E> extends AbstractSet<E> implements SequencedSet<E> {
31 private final LinkedHashMap<WeakKey<E>, Object> map = new LinkedHashMap<>();
32 private static final Object PRESENT = new Object();
33
39 super();
40 }
41
50 public WeakLinkedHashSet(Collection<? extends E> collection) {
51 requireNonNullParam(collection, "collection", "WeakLinkedHashSet");
52 addAll(collection);
53 }
54
55 @Override
56 public boolean add(E e) {
57 requireNonNullParam(e, "e", "WeakLinkedHashSet.add");
58
59 purgeCollected();
60 return map.putLast(new WeakKey<>(e), PRESENT) == null;
61 }
62
63 @Override
64 public void addFirst(E e) {
65 requireNonNullParam(e, "e", "WeakLinkedHashSet.addFirst");
66
67 purgeCollected();
68 map.putFirst(new WeakKey<>(e), PRESENT);
69 }
70
71 @Override
72 public void addLast(E e) {
73 requireNonNullParam(e, "e", "WeakLinkedHashSet.addLast");
74
75 purgeCollected();
76 map.putLast(new WeakKey<>(e), PRESENT);
77 }
78
79 @Override
80 public boolean remove(Object o) {
81 requireNonNullParam(o, "o", "WeakLinkedHashSet.remove");
82
83 purgeCollected();
84 return map.remove(new WeakKey<>(o)) != null;
85 }
86
87 @Override
88 public boolean contains(Object o) {
89 requireNonNullParam(o, "o", "WeakLinkedHashSet.contains");
90
91 purgeCollected();
92 return map.containsKey(new WeakKey<>(o));
93 }
94
95 @Override
96 public int size() {
97 purgeCollected();
98 return map.size();
99 }
100
101 // Removes entries where the element has been garbage collected
102 private void purgeCollected() {
103 map.keySet().removeIf(key -> key.get() == null);
104 }
105
106 @Override
107 public Iterator<E> iterator() {
108 purgeCollected();
109 return new WeakKeyIterator(map.keySet().iterator());
110 }
111
112 @Override
113 public SequencedSet<E> reversed() {
114 purgeCollected();
115
116 return new ReversedView<>(this, map.sequencedKeySet().reversed());
117 }
118
119 @Override
120 public Spliterator<E> spliterator() {
121 return Spliterators.spliteratorUnknownSize(
122 iterator(), Spliterator.DISTINCT | Spliterator.ORDERED | Spliterator.NONNULL);
123 }
124
125 private static final class WeakKey<T> extends WeakReference<T> {
126 private final int m_hashCode;
127
128 WeakKey(T referent) {
129 super(referent);
130 m_hashCode = referent.hashCode();
131 }
132
133 @Override
134 public boolean equals(Object obj) {
135 if (!(obj instanceof WeakKey<?> other)) {
136 return false;
137 }
138
139 T ref = get();
140 return ref != null && ref.equals(other.get());
141 }
142
143 @Override
144 public int hashCode() {
145 return m_hashCode;
146 }
147 }
148
149 private class WeakKeyIterator implements Iterator<E> {
150 private final ArrayList<WeakKey<E>> keys = new ArrayList<>();
151 private int nextIndex;
152 private E nextElement = null;
153 private E lastReturnedElement = null;
154
155 WeakKeyIterator(Iterator<WeakKey<E>> mapIterator) {
156 mapIterator.forEachRemaining(keys::add);
157 }
158
159 @Override
160 public boolean hasNext() {
161 while (nextElement == null && nextIndex < keys.size()) {
162 WeakKey<E> key = keys.get(nextIndex++);
163 nextElement = key.get();
164 if (nextElement == null) {
165 map.remove(key);
166 }
167 }
168 return nextElement != null;
169 }
170
171 @Override
172 public E next() {
173 if (!hasNext()) {
174 throw new NoSuchElementException();
175 }
176 E element = nextElement;
177 lastReturnedElement = element;
178 nextElement = null;
179 return element;
180 }
181
182 @Override
183 public void remove() {
184 if (lastReturnedElement == null) {
185 throw new IllegalStateException();
186 }
187
188 map.remove(new WeakKey<>(lastReturnedElement));
189 lastReturnedElement = null;
190 }
191 }
192
193 private static class ReversedView<E> extends AbstractSet<E> implements SequencedSet<E> {
194 private final WeakLinkedHashSet<E> originalSet;
195 private final SequencedSet<WeakKey<E>> reversedKeys;
196
197 ReversedView(WeakLinkedHashSet<E> originalSet, SequencedSet<WeakKey<E>> reversedKeys) {
198 this.originalSet = originalSet;
199 this.reversedKeys = reversedKeys;
200 }
201
202 @Override
203 public int size() {
204 return originalSet.size();
205 }
206
207 @Override
208 public Iterator<E> iterator() {
209 return originalSet.new WeakKeyIterator(reversedKeys.iterator());
210 }
211
212 @Override
213 public SequencedSet<E> reversed() {
214 return originalSet; // Reversing a reversed view returns the original set
215 }
216
217 @Override
218 public boolean add(E e) {
219 return originalSet.add(e);
220 }
221
222 @Override
223 public boolean remove(Object o) {
224 return originalSet.remove(o);
225 }
226
227 @Override
228 public boolean contains(Object o) {
229 return originalSet.contains(o);
230 }
231
232 @Override
233 public void addFirst(E e) {
234 originalSet.addLast(e);
235 }
236
237 @Override
238 public void addLast(E e) {
239 originalSet.addFirst(e);
240 }
241
242 @Override
243 public E getFirst() {
244 return originalSet.getLast();
245 }
246
247 @Override
248 public E getLast() {
249 return originalSet.getFirst();
250 }
251
252 @Override
253 public E removeFirst() {
254 return originalSet.removeLast();
255 }
256
257 @Override
258 public E removeLast() {
259 return originalSet.removeFirst();
260 }
261
262 @Override
263 public Spliterator<E> spliterator() {
264 return Spliterators.spliteratorUnknownSize(
265 iterator(), Spliterator.DISTINCT | Spliterator.ORDERED | Spliterator.NONNULL);
266 }
267 }
268}
WeakLinkedHashSet(Collection<? extends E > collection)