| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package org.apache.ignite.internal.util; |
| |
| import java.util.Collection; |
| import java.util.Comparator; |
| import java.util.Iterator; |
| import java.util.Map; |
| import java.util.NavigableSet; |
| import java.util.NoSuchElementException; |
| import java.util.Set; |
| import java.util.SortedSet; |
| import java.util.concurrent.ConcurrentNavigableMap; |
| import java.util.concurrent.ConcurrentSkipListMap; |
| import java.util.concurrent.ConcurrentSkipListSet; |
| import org.jetbrains.annotations.Nullable; |
| |
| import static java.lang.Boolean.TRUE; |
| |
| /** |
| * This class provided the same logic as {@link ConcurrentSkipListSet}. It adds |
| * methods {@link #firstx()} and {@link #lastx()}, which unlike {@link #first()} |
| * and {@link #last()} methods return {@code null} for empty sets instead of |
| * throwing {@link NoSuchElementException}. |
| */ |
| public class GridConcurrentSkipListSet<E> extends GridSerializableSet<E> implements NavigableSet<E>, Cloneable { |
| /** */ |
| private static final long serialVersionUID = 0L; |
| |
| /** |
| * The underlying map. Uses Boolean.TRUE as value for each |
| * element. |
| */ |
| private ConcurrentNavigableMap<E, Object> m; |
| |
| /** |
| * Constructs a new, empty set that orders its elements according to |
| * their {@linkplain Comparable natural ordering}. |
| */ |
| public GridConcurrentSkipListSet() { |
| m = new ConcurrentSkipListMap<>(); |
| } |
| |
| /** |
| * Constructs a new, empty set that orders its elements according to |
| * the specified comparator. |
| * |
| * @param comp the comparator that will be used to order this set. |
| * If <tt>null</tt>, the {@linkplain Comparable natural |
| * ordering} of the elements will be used. |
| */ |
| public GridConcurrentSkipListSet(Comparator<? super E> comp) { |
| m = new ConcurrentSkipListMap<>(comp); |
| } |
| |
| /** |
| * Constructs a new set containing the elements in the specified |
| * collection, that orders its elements according to their |
| * {@linkplain Comparable natural ordering}. |
| * |
| * @param c The elements that will comprise the new set |
| * @throws ClassCastException if the elements in <tt>c</tt> are |
| * not {@link Comparable}, or are not mutually comparable |
| * @throws NullPointerException if the specified collection or any |
| * of its elements are null |
| */ |
| public GridConcurrentSkipListSet(Collection<? extends E> c) { |
| m = new ConcurrentSkipListMap<>(); |
| addAll(c); |
| } |
| |
| /** |
| * Constructs a new set containing the same elements and using the |
| * same ordering as the specified sorted set. |
| * |
| * @param s sorted set whose elements will comprise the new set |
| * @throws NullPointerException if the specified sorted set or any |
| * of its elements are null |
| */ |
| public GridConcurrentSkipListSet(SortedSet<E> s) { |
| m = new ConcurrentSkipListMap<>(s.comparator()); |
| |
| addAll(s); |
| } |
| |
| /** |
| * For use by submaps. |
| * |
| * @param m Base map. |
| */ |
| private GridConcurrentSkipListSet(ConcurrentNavigableMap<E, Object> m) { |
| this.m = m; |
| } |
| |
| /** {@inheritDoc} */ |
| @SuppressWarnings({"CloneCallsConstructors"}) |
| @Override public GridConcurrentSkipListSet<E> clone() { |
| try { |
| GridConcurrentSkipListSet<E> clone = (GridConcurrentSkipListSet<E>)super.clone(); |
| |
| clone.m = new ConcurrentSkipListMap<>(m); |
| |
| return clone; |
| } |
| catch (CloneNotSupportedException ignored) { |
| throw new Error("Clone should be supported on GridConcurrentSkipListSet class: " + this); |
| } |
| } |
| |
| /** {@inheritDoc} */ |
| @Override public int size() { |
| return m.size(); |
| } |
| |
| /** {@inheritDoc} */ |
| @Override public boolean isEmpty() { |
| return m.isEmpty(); |
| } |
| |
| /** {@inheritDoc} */ |
| @SuppressWarnings({"SuspiciousMethodCalls"}) |
| @Override public boolean contains(Object o) { |
| return m.containsKey(o); |
| } |
| |
| /** {@inheritDoc} */ |
| @Override public boolean add(E e) { |
| return m.putIfAbsent(e, TRUE) == null; |
| } |
| |
| /** {@inheritDoc} */ |
| @Override public boolean remove(Object o) { |
| return m.remove(o, TRUE); |
| } |
| |
| /** {@inheritDoc} */ |
| @Override public void clear() { |
| m.clear(); |
| } |
| |
| /** {@inheritDoc} */ |
| @Override public Iterator<E> iterator() { |
| return m.navigableKeySet().iterator(); |
| } |
| |
| /** {@inheritDoc} */ |
| @Override public Iterator<E> descendingIterator() { |
| return m.descendingKeySet().iterator(); |
| } |
| |
| /** {@inheritDoc} */ |
| @Override public boolean equals(Object o) { |
| // Override AbstractSet version to avoid calling size() |
| if (o == this) |
| return true; |
| |
| if (!(o instanceof Set)) |
| return false; |
| |
| Collection<?> c = (Collection<?>)o; |
| |
| try { |
| return containsAll(c) && c.containsAll(this); |
| } |
| catch (ClassCastException ignored) { |
| return false; |
| } |
| catch (NullPointerException ignored) { |
| return false; |
| } |
| } |
| |
| /** {@inheritDoc} */ |
| @Override public int hashCode() { |
| return super.hashCode(); |
| } |
| |
| /** {@inheritDoc} */ |
| @Override public boolean removeAll(Collection<?> c) { |
| // Override AbstractSet version to avoid unnecessary call to size() |
| boolean modified = false; |
| |
| for (Object o : c) |
| if (remove(o)) |
| modified = true; |
| |
| return modified; |
| } |
| |
| /** {@inheritDoc} */ |
| @Override public E lower(E e) { |
| return m.lowerKey(e); |
| } |
| |
| /** {@inheritDoc} */ |
| @Override public E floor(E e) { |
| return m.floorKey(e); |
| } |
| |
| /** {@inheritDoc} */ |
| @Override public E ceiling(E e) { |
| return m.ceilingKey(e); |
| } |
| |
| /** {@inheritDoc} */ |
| @Override public E higher(E e) { |
| return m.higherKey(e); |
| } |
| |
| /** {@inheritDoc} */ |
| @Nullable @Override public E pollFirst() { |
| Map.Entry<E, Object> e = m.pollFirstEntry(); |
| |
| return e == null ? null : e.getKey(); |
| } |
| |
| /** {@inheritDoc} */ |
| @Nullable @Override public E pollLast() { |
| Map.Entry<E, Object> e = m.pollLastEntry(); |
| |
| return e == null ? null : e.getKey(); |
| } |
| |
| /** {@inheritDoc} */ |
| @Override public Comparator<? super E> comparator() { |
| return m.comparator(); |
| } |
| |
| /** {@inheritDoc} */ |
| @Override public E first() { |
| return m.firstKey(); |
| } |
| |
| /** |
| * Same as {@link #first()}, but returns {@code null} if set is empty. |
| * |
| * @return First entry or {@code null} if set is empty. |
| */ |
| @Nullable public E firstx() { |
| Map.Entry<E, Object> e = m.firstEntry(); |
| |
| return e == null ? null : e.getKey(); |
| } |
| |
| /** {@inheritDoc} */ |
| @Override public E last() { |
| return m.lastKey(); |
| } |
| |
| /** |
| * Same as {@link #last()}, but returns {@code null} if set is empty. |
| * |
| * @return Last entry or {@code null} if set is empty. |
| */ |
| @Nullable public E lastx() { |
| Map.Entry<E, Object> e = m.lastEntry(); |
| |
| return e == null ? null : e.getKey(); |
| } |
| |
| /** {@inheritDoc} */ |
| @Override public NavigableSet<E> subSet(E fromElement, boolean fromInclusive, E toElement, boolean toInclusive) { |
| return new GridConcurrentSkipListSet<>(m.subMap(fromElement, fromInclusive, toElement, toInclusive)); |
| } |
| |
| /** {@inheritDoc} */ |
| @Override public NavigableSet<E> headSet(E toElement, boolean inclusive) { |
| return new GridConcurrentSkipListSet<>(m.headMap(toElement, inclusive)); |
| } |
| |
| /** {@inheritDoc} */ |
| @Override public NavigableSet<E> tailSet(E fromElement, boolean inclusive) { |
| return new GridConcurrentSkipListSet<>(m.tailMap(fromElement, inclusive)); |
| } |
| |
| /** {@inheritDoc} */ |
| @Override public NavigableSet<E> subSet(E fromElement, E toElement) { |
| return subSet(fromElement, true, toElement, false); |
| } |
| |
| /** {@inheritDoc} */ |
| @Override public NavigableSet<E> headSet(E toElement) { |
| return headSet(toElement, false); |
| } |
| |
| /** {@inheritDoc} */ |
| @Override public NavigableSet<E> tailSet(E fromElement) { |
| return tailSet(fromElement, true); |
| } |
| |
| /** {@inheritDoc} */ |
| @Override public NavigableSet<E> descendingSet() { |
| return new GridConcurrentSkipListSet<>(m.descendingMap()); |
| } |
| } |