001/*
002 * JPPF.
003 * Copyright (C) 2005-2018 JPPF Team.
004 * http://www.jppf.org
005 *
006 * Licensed under the Apache License, Version 2.0 (the "License");
007 * you may not use this file except in compliance with the License.
008 * You may obtain a copy of the License at
009 *
010 *   http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018
019package org.jppf.utils.collections;
020
021import java.util.*;
022import java.util.concurrent.ConcurrentHashMap;
023
024/**
025 * A concurrent {@link Set set} implementation backed by a {@link ConcurrentHashMap}.
026 * @param <E> the type of objects in the set.
027 * @author Laurent Cohen
028 */
029public class ConcurrentHashSet<E> implements Set<E> {
030  /**
031   * The backing map for this concurrent hash set.
032   */
033  private final Map<E, Boolean> map;
034
035  /**
036   * Create a new, empty set with a default initial capacity of 16, a load factor of 0.75 and a concurrency level of 16.
037   */
038  public ConcurrentHashSet() {
039    map = new ConcurrentHashMap<>();
040  }
041
042  /**
043   * Create a new, empty set with the specified initial capacity, a load factor of 0.75 and a concurrency level of 16
044   * @param initialCapacity the initial capacity.
045   */
046  public ConcurrentHashSet(final int initialCapacity) {
047    map = new ConcurrentHashMap<>(initialCapacity);
048  }
049
050  /**
051   * Create a new, empty set with the specified initial capacity, load factor and a concurrency level of 16.
052   * @param initialCapacity the initial capacity.
053   * @param loadFactor the load factor threshold, used to control resizing.
054   */
055  public ConcurrentHashSet(final int initialCapacity, final float loadFactor) {
056    map = new ConcurrentHashMap<>(initialCapacity, loadFactor);
057  }
058
059  /**
060   * Create a new, empty map with the specified initial capacity, load factor and concurrency level.
061   * @param initialCapacity the initial capacity.
062   * @param loadFactor the load factor threshold, used to control resizing.
063   * @param concurrencyLevel the estimated number of concurrently updating threads.
064   */
065  public ConcurrentHashSet(final int initialCapacity, final float loadFactor, final int concurrencyLevel) {
066    map = new ConcurrentHashMap<>(initialCapacity, loadFactor, concurrencyLevel);
067  }
068
069  @Override
070  public int size() {
071    return map.size();
072  }
073
074  @Override
075  public boolean isEmpty() {
076    return map.isEmpty();
077  }
078
079  @Override
080  public boolean contains(final Object o) {
081    return map.containsKey(o);
082  }
083
084  @Override
085  public Iterator<E> iterator() {
086    return map.keySet().iterator();
087  }
088
089  @Override
090  public Object[] toArray() {
091    return map.keySet().toArray();
092  }
093
094  @Override
095  public <T> T[] toArray(final T[] a) {
096    return map.keySet().toArray(a);
097  }
098
099  @Override
100  public boolean add(final E e) {
101    return map.put(e, Boolean.TRUE) == null;
102  }
103
104  @Override
105  public boolean remove(final Object o) {
106    return map.remove(o) != null;
107  }
108
109  @Override
110  public boolean containsAll(final Collection<?> c) {
111    return map.keySet().containsAll(c);
112  }
113
114  @Override
115  public boolean addAll(final Collection<? extends E> c) {
116    boolean result = false;
117    for (E e: c) result |= add(e);
118    return result;
119  }
120
121  @Override
122  public boolean retainAll(final Collection<?> c) {
123    int count = 0;
124    final Iterator<E> it = iterator();
125    while (it.hasNext()) {
126      final E e = it.next();
127      if (!c.contains(e)) {
128        it.remove();
129        count++;
130      }
131    }
132    return count > 0;
133  }
134
135  @Override
136  public boolean removeAll(final Collection<?> c) {
137    boolean result = false;
138    for (final Object o: c) result |= remove(o);
139    return result;
140  }
141
142  @Override
143  public void clear() {
144    map.clear();
145  }
146}