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.hbase.classification.InterfaceAudience;
29  import org.apache.hadoop.hbase.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.Private
49  public class SortedCopyOnWriteSet<E> implements SortedSet<E> {
50    private volatile SortedSet<E> internalSet;
51  
52    public SortedCopyOnWriteSet() {
53      this.internalSet = new TreeSet<E>();
54    }
55  
56    public SortedCopyOnWriteSet(Collection<? extends E> c) {
57      this.internalSet = new TreeSet<E>(c);
58    }
59  
60    public SortedCopyOnWriteSet(Comparator<? super E> comparator) {
61      this.internalSet = new TreeSet<E>(comparator);
62    }
63  
64    @Override
65    public int size() {
66      return internalSet.size();
67    }
68  
69    @Override
70    public boolean isEmpty() {
71      return internalSet.isEmpty();
72    }
73  
74    @Override
75    public boolean contains(Object o) {
76      return internalSet.contains(o);
77    }
78  
79    @Override
80    public Iterator<E> iterator() {
81      return internalSet.iterator();
82    }
83  
84    @Override
85    public Object[] toArray() {
86      return internalSet.toArray();
87    }
88  
89    @Override
90    public <T> T[] toArray(T[] a) {
91      return internalSet.toArray(a);
92    }
93  
94    @Override
95    public synchronized boolean add(E e) {
96      SortedSet<E> newSet = new TreeSet<E>(internalSet);
97      boolean added = newSet.add(e);
98      internalSet = newSet;
99      return added;
100   }
101 
102   @Override
103   public synchronized boolean remove(Object o) {
104     SortedSet<E> newSet = new TreeSet<E>(internalSet);
105     boolean removed = newSet.remove(o);
106     internalSet = newSet;
107     return removed;
108   }
109 
110   @Override
111   public boolean containsAll(Collection<?> c) {
112     return internalSet.containsAll(c);
113   }
114 
115   @Override
116   public synchronized boolean addAll(Collection<? extends E> c) {
117     SortedSet<E> newSet = new TreeSet<E>(internalSet);
118     boolean changed = newSet.addAll(c);
119     internalSet = newSet;
120     return changed;
121   }
122 
123   @Override
124   public synchronized boolean retainAll(Collection<?> c) {
125     SortedSet<E> newSet = new TreeSet<E>(internalSet);
126     boolean changed = newSet.retainAll(c);
127     internalSet = newSet;
128     return changed;
129   }
130 
131   @Override
132   public synchronized boolean removeAll(Collection<?> c) {
133     SortedSet<E> newSet = new TreeSet<E>(internalSet);
134     boolean changed = newSet.removeAll(c);
135     internalSet = newSet;
136     return changed;
137   }
138 
139   @Override
140   public synchronized void clear() {
141     Comparator<? super E> comparator = internalSet.comparator();
142     if (comparator != null) {
143       internalSet = new TreeSet<E>(comparator);
144     } else {
145       internalSet = new TreeSet<E>();
146     }
147   }
148 
149   @Override
150   public Comparator<? super E> comparator() {
151     return internalSet.comparator();
152   }
153 
154   @Override
155   public SortedSet<E> subSet(E fromElement, E toElement) {
156     return internalSet.subSet(fromElement, toElement);
157   }
158 
159   @Override
160   public SortedSet<E> headSet(E toElement) {
161     return internalSet.headSet(toElement);
162   }
163 
164   @Override
165   public SortedSet<E> tailSet(E fromElement) {
166     return internalSet.tailSet(fromElement);
167   }
168 
169   @Override
170   public E first() {
171     return internalSet.first();
172   }
173 
174   @Override
175   public E last() {
176     return internalSet.last();
177   }
178 }