1 /*
2  * Copyright (c) 2021, 2023, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.  Oracle designates this
8  * particular file as subject to the "Classpath" exception as provided
9  * by Oracle in the LICENSE file that accompanied this code.
10  *
11  * This code is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14  * version 2 for more details (a copy is included in the LICENSE file that
15  * accompanied this code).
16  *
17  * You should have received a copy of the GNU General Public License version
18  * 2 along with this work; if not, write to the Free Software Foundation,
19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20  *
21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22  * or visit www.oracle.com if you need additional information or have any
23  * questions.
24  */
25 
26 package java.util;
27 
28 import java.util.function.Consumer;
29 import java.util.function.IntFunction;
30 import java.util.stream.Stream;
31 import java.util.stream.StreamSupport;
32 import jdk.internal.util.ArraysSupport;
33 
34 /**
35  * Provides a reverse-ordered view of any Deque. Not serializable.
36  */
37 class ReverseOrderDequeView<E> implements Deque<E> {
38     final Deque<E> base;
39 
ReverseOrderDequeView(Deque<E> deque)40     private ReverseOrderDequeView(Deque<E> deque) {
41         base = deque;
42     }
43 
of(Deque<T> deque)44     public static <T> Deque<T> of(Deque<T> deque) {
45         if (deque instanceof ReverseOrderDequeView<T> rodv) {
46             return rodv.base;
47         } else {
48             return new ReverseOrderDequeView<>(deque);
49         }
50     }
51 
52     // ========== Iterable ==========
53 
forEach(Consumer<? super E> action)54     public void forEach(Consumer<? super E> action) {
55         for (E e : this)
56             action.accept(e);
57     }
58 
iterator()59     public Iterator<E> iterator() {
60         return base.descendingIterator();
61     }
62 
spliterator()63     public Spliterator<E> spliterator() {
64         return Spliterators.spliterator(this, Spliterator.ORDERED);
65     }
66 
67     // ========== Collection ==========
68 
add(E e)69     public boolean add(E e) {
70         base.addFirst(e);
71         return true;
72     }
73 
addAll(Collection<? extends E> c)74     public boolean addAll(Collection<? extends E> c) {
75         boolean modified = false;
76         for (E e : c) {
77             base.addFirst(e);
78             modified = true;
79         }
80         return modified;
81     }
82 
clear()83     public void clear() {
84         base.clear();
85     }
86 
contains(Object o)87     public boolean contains(Object o) {
88         return base.contains(o);
89     }
90 
containsAll(Collection<?> c)91     public boolean containsAll(Collection<?> c) {
92         return base.containsAll(c);
93     }
94 
isEmpty()95     public boolean isEmpty() {
96         return base.isEmpty();
97     }
98 
parallelStream()99     public Stream<E> parallelStream() {
100         return StreamSupport.stream(spliterator(), true);
101     }
102 
103     // copied from AbstractCollection
remove(Object o)104     public boolean remove(Object o) {
105         Iterator<E> it = iterator();
106         if (o==null) {
107             while (it.hasNext()) {
108                 if (it.next()==null) {
109                     it.remove();
110                     return true;
111                 }
112             }
113         } else {
114             while (it.hasNext()) {
115                 if (o.equals(it.next())) {
116                     it.remove();
117                     return true;
118                 }
119             }
120         }
121         return false;
122     }
123 
124     // copied from AbstractCollection
removeAll(Collection<?> c)125     public boolean removeAll(Collection<?> c) {
126         Objects.requireNonNull(c);
127         boolean modified = false;
128         Iterator<?> it = iterator();
129         while (it.hasNext()) {
130             if (c.contains(it.next())) {
131                 it.remove();
132                 modified = true;
133             }
134         }
135         return modified;
136     }
137 
138     // copied from AbstractCollection
retainAll(Collection<?> c)139     public boolean retainAll(Collection<?> c) {
140         Objects.requireNonNull(c);
141         boolean modified = false;
142         Iterator<E> it = iterator();
143         while (it.hasNext()) {
144             if (!c.contains(it.next())) {
145                 it.remove();
146                 modified = true;
147             }
148         }
149         return modified;
150     }
151 
size()152     public int size() {
153         return base.size();
154     }
155 
stream()156     public Stream<E> stream() {
157         return StreamSupport.stream(spliterator(), false);
158     }
159 
toArray()160     public Object[] toArray() {
161         return ArraysSupport.reverse(base.toArray());
162     }
163 
164     @SuppressWarnings("unchecked")
toArray(T[] a)165     public <T> T[] toArray(T[] a) {
166         return ArraysSupport.toArrayReversed(base, a);
167     }
168 
toArray(IntFunction<T[]> generator)169     public <T> T[] toArray(IntFunction<T[]> generator) {
170         return ArraysSupport.reverse(base.toArray(generator));
171     }
172 
173     // copied from AbstractCollection
toString()174     public String toString() {
175         Iterator<E> it = iterator();
176         if (! it.hasNext())
177             return "[]";
178 
179         StringBuilder sb = new StringBuilder();
180         sb.append('[');
181         for (;;) {
182             E e = it.next();
183             sb.append(e == this ? "(this Collection)" : e);
184             if (! it.hasNext())
185                 return sb.append(']').toString();
186             sb.append(',').append(' ');
187         }
188     }
189 
190     // ========== Deque and Queue ==========
191 
addFirst(E e)192     public void addFirst(E e) {
193         base.addLast(e);
194     }
195 
addLast(E e)196     public void addLast(E e) {
197         base.addFirst(e);
198     }
199 
descendingIterator()200     public Iterator<E> descendingIterator() {
201         return base.iterator();
202     }
203 
element()204     public E element() {
205         return base.getLast();
206     }
207 
getFirst()208     public E getFirst() {
209         return base.getLast();
210     }
211 
getLast()212     public E getLast() {
213         return base.getFirst();
214     }
215 
offer(E e)216     public boolean offer(E e) {
217         return base.offerFirst(e);
218     }
219 
offerFirst(E e)220     public boolean offerFirst(E e) {
221         return base.offerLast(e);
222     }
223 
offerLast(E e)224     public boolean offerLast(E e) {
225         return base.offerFirst(e);
226     }
227 
peek()228     public E peek() {
229         return base.peekLast();
230     }
231 
peekFirst()232     public E peekFirst() {
233         return base.peekLast();
234     }
235 
peekLast()236     public E peekLast() {
237         return base.peekFirst();
238     }
239 
poll()240     public E poll() {
241         return base.pollLast();
242     }
243 
pollFirst()244     public E pollFirst() {
245         return base.pollLast();
246     }
247 
pollLast()248     public E pollLast() {
249         return base.pollFirst();
250     }
251 
pop()252     public E pop() {
253         return base.removeLast();
254     }
255 
push(E e)256     public void push(E e) {
257         base.addLast(e);
258     }
259 
remove()260     public E remove() {
261         return base.removeLast();
262     }
263 
removeFirst()264     public E removeFirst() {
265         return base.removeLast();
266     }
267 
removeLast()268     public E removeLast() {
269         return base.removeFirst();
270     }
271 
removeFirstOccurrence(Object o)272     public boolean removeFirstOccurrence(Object o) {
273         return base.removeLastOccurrence(o);
274     }
275 
removeLastOccurrence(Object o)276     public boolean removeLastOccurrence(Object o) {
277         return base.removeFirstOccurrence(o);
278     }
279 }
280