1 | /* |
2 | * Copyright 2004-2014 H2 Group. Multiple-Licensed under the MPL 2.0, |
3 | * and the EPL 1.0 (http://h2database.com/html/license.html). |
4 | * Initial Developer: H2 Group |
5 | */ |
6 | package org.h2.mvstore; |
7 | |
8 | import java.util.Arrays; |
9 | import java.util.Iterator; |
10 | |
11 | /** |
12 | * A very simple array list that supports concurrent access. |
13 | * Internally, it uses immutable objects. |
14 | * |
15 | * @param <K> the key type |
16 | */ |
17 | public class ConcurrentArrayList<K> { |
18 | |
19 | /** |
20 | * The array. |
21 | */ |
22 | @SuppressWarnings("unchecked") |
23 | K[] array = (K[]) new Object[0]; |
24 | |
25 | /** |
26 | * Get the first element, or null if none. |
27 | * |
28 | * @return the first element |
29 | */ |
30 | public K peekFirst() { |
31 | K[] a = array; |
32 | return a.length == 0 ? null : a[0]; |
33 | } |
34 | |
35 | /** |
36 | * Get the last element, or null if none. |
37 | * |
38 | * @return the last element |
39 | */ |
40 | public K peekLast() { |
41 | K[] a = array; |
42 | int len = a.length; |
43 | return len == 0 ? null : a[len - 1]; |
44 | } |
45 | |
46 | /** |
47 | * Add an element at the end. |
48 | * |
49 | * @param obj the element |
50 | */ |
51 | public synchronized void add(K obj) { |
52 | int len = array.length; |
53 | array = Arrays.copyOf(array, len + 1); |
54 | array[len] = obj; |
55 | } |
56 | |
57 | /** |
58 | * Remove the first element, if it matches. |
59 | * |
60 | * @param obj the element to remove |
61 | * @return true if the element matched and was removed |
62 | */ |
63 | public synchronized boolean removeFirst(K obj) { |
64 | if (peekFirst() != obj) { |
65 | return false; |
66 | } |
67 | int len = array.length; |
68 | @SuppressWarnings("unchecked") |
69 | K[] a = (K[]) new Object[len - 1]; |
70 | System.arraycopy(array, 1, a, 0, len - 1); |
71 | array = a; |
72 | return true; |
73 | } |
74 | |
75 | /** |
76 | * Remove the last element, if it matches. |
77 | * |
78 | * @param obj the element to remove |
79 | * @return true if the element matched and was removed |
80 | */ |
81 | public synchronized boolean removeLast(K obj) { |
82 | if (peekLast() != obj) { |
83 | return false; |
84 | } |
85 | array = Arrays.copyOf(array, array.length - 1); |
86 | return true; |
87 | } |
88 | |
89 | /** |
90 | * Get an iterator over all entries. |
91 | * |
92 | * @return the iterator |
93 | */ |
94 | public Iterator<K> iterator() { |
95 | return new Iterator<K>() { |
96 | |
97 | K[] a = array; |
98 | int index; |
99 | |
100 | @Override |
101 | public boolean hasNext() { |
102 | return index < a.length; |
103 | } |
104 | |
105 | @Override |
106 | public K next() { |
107 | return a[index++]; |
108 | } |
109 | |
110 | @Override |
111 | public void remove() { |
112 | throw DataUtils.newUnsupportedOperationException("remove"); |
113 | } |
114 | |
115 | }; |
116 | } |
117 | |
118 | } |