View Javadoc

1   /*
2    *
3    * Licensed to the Apache Software Foundation (ASF) under one
4    * or more contributor license agreements.  See the NOTICE file
5    * distributed with this work for additional information
6    * regarding copyright ownership.  The ASF licenses this file
7    * to you under the Apache License, Version 2.0 (the
8    * "License"); you may not use this file except in compliance
9    * with the License.  You may obtain a copy of the License at
10   *
11   *     http://www.apache.org/licenses/LICENSE-2.0
12   *
13   * Unless required by applicable law or agreed to in writing, software
14   * distributed under the License is distributed on an "AS IS" BASIS,
15   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16   * See the License for the specific language governing permissions and
17   * limitations under the License.
18   */
19  
20  package org.apache.hadoop.hbase.util;
21  
22  import java.util.Collection;
23  import java.util.Comparator;
24  import java.util.Iterator;
25  import java.util.SortedSet;
26  import java.util.TreeSet;
27  
28  import org.apache.hadoop.classification.InterfaceAudience;
29  import org.apache.hadoop.classification.InterfaceStability;
30  
31  /**
32   * Simple {@link java.util.SortedSet} implementation that uses an internal
33   * {@link java.util.TreeSet} to provide ordering. All mutation operations
34   * create a new copy of the <code>TreeSet</code> instance, so are very
35   * expensive.  This class is only intended for use on small, very rarely
36   * written collections that expect highly concurrent reads. Read operations
37   * are performed on a reference to the internal <code>TreeSet</code> at the
38   * time of invocation, so will not see any mutations to the collection during
39   * their operation.
40   *
41   * <p>Note that due to the use of a {@link java.util.TreeSet} internally,
42   * a {@link java.util.Comparator} instance must be provided, or collection
43   * elements must implement {@link java.lang.Comparable}.
44   * </p>
45   * @param <E> A class implementing {@link java.lang.Comparable} or able to be
46   * compared by a provided comparator.
47   */
48  @InterfaceAudience.Public
49  @InterfaceStability.Stable
50  public class SortedCopyOnWriteSet<E> implements SortedSet<E> {
51    private volatile SortedSet<E> internalSet;
52  
53    public SortedCopyOnWriteSet() {
54      this.internalSet = new TreeSet<E>();
55    }
56  
57    public SortedCopyOnWriteSet(Collection<? extends E> c) {
58      this.internalSet = new TreeSet<E>(c);
59    }
60  
61    public SortedCopyOnWriteSet(Comparator<? super E> comparator) {
62      this.internalSet = new TreeSet<E>(comparator);
63    }
64  
65    @Override
66    public int size() {
67      return internalSet.size();
68    }
69  
70    @Override
71    public boolean isEmpty() {
72      return internalSet.isEmpty();
73    }
74  
75    @Override
76    public boolean contains(Object o) {
77      return internalSet.contains(o);
78    }
79  
80    @Override
81    public Iterator<E> iterator() {
82      return internalSet.iterator();
83    }
84  
85    @Override
86    public Object[] toArray() {
87      return internalSet.toArray();
88    }
89  
90    @Override
91    public <T> T[] toArray(T[] a) {
92      return internalSet.toArray(a);
93    }
94  
95    @Override
96    public synchronized boolean add(E e) {
97      SortedSet<E> newSet = new TreeSet<E>(internalSet);
98      boolean added = newSet.add(e);
99      internalSet = newSet;
100     return added;
101   }
102 
103   @Override
104   public synchronized boolean remove(Object o) {
105     SortedSet<E> newSet = new TreeSet<E>(internalSet);
106     boolean removed = newSet.remove(o);
107     internalSet = newSet;
108     return removed;
109   }
110 
111   @Override
112   public boolean containsAll(Collection<?> c) {
113     return internalSet.containsAll(c);
114   }
115 
116   @Override
117   public synchronized boolean addAll(Collection<? extends E> c) {
118     SortedSet<E> newSet = new TreeSet<E>(internalSet);
119     boolean changed = newSet.addAll(c);
120     internalSet = newSet;
121     return changed;
122   }
123 
124   @Override
125   public synchronized boolean retainAll(Collection<?> c) {
126     SortedSet<E> newSet = new TreeSet<E>(internalSet);
127     boolean changed = newSet.retainAll(c);
128     internalSet = newSet;
129     return changed;
130   }
131 
132   @Override
133   public synchronized boolean removeAll(Collection<?> c) {
134     SortedSet<E> newSet = new TreeSet<E>(internalSet);
135     boolean changed = newSet.removeAll(c);
136     internalSet = newSet;
137     return changed;
138   }
139 
140   @Override
141   public synchronized void clear() {
142     Comparator<? super E> comparator = internalSet.comparator();
143     if (comparator != null) {
144       internalSet = new TreeSet<E>(comparator);
145     } else {
146       internalSet = new TreeSet<E>();
147     }
148   }
149 
150   @Override
151   public Comparator<? super E> comparator() {
152     return internalSet.comparator();
153   }
154 
155   @Override
156   public SortedSet<E> subSet(E fromElement, E toElement) {
157     return internalSet.subSet(fromElement, toElement);
158   }
159 
160   @Override
161   public SortedSet<E> headSet(E toElement) {
162     return internalSet.headSet(toElement);
163   }
164 
165   @Override
166   public SortedSet<E> tailSet(E fromElement) {
167     return internalSet.tailSet(fromElement);
168   }
169 
170   @Override
171   public E first() {
172     return internalSet.first();
173   }
174 
175   @Override
176   public E last() {
177     return internalSet.last();
178   }
179 }