Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
// Copyright 2015 PlanBase Inc. & Glen Peterson
//
// Licensed 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.organicdesign.fp.collections;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.function.Predicate;
/**
Don't implement this interface directly if you don't have to. A collection is an
{@link java.lang.Iterable} with a size (a size() method) and unfortunately a contains() method
(deprecated on Lists).
Collection defines the return of Map.values() which can have duplicates and may be ordered, or
unordered. For this reason, I don't think it's possible to define an equals() method on Collection
that works in all circumstances (when comparing it to a List, a Set, or another amorphous
Collection). I don't think Map.values() would exist if Generics had existed and Map had
implemented Iterable<Entry> from the beginning.
UnmodCollection is an unmodifiable version of {@link java.util.Collection}
which formalizes the return type of Collections.unmodifiableCollection() and Map.values().
*/
public interface UnmodCollection extends Collection, UnmodIterable {
// ========================================== Static ==========================================
// /**
// Don't use this. There may not be any way to implement equals() meaningfully on a Collection
// because the definition of Collection is too broad.
//
// Implements equals and hashCode() methods to make defining unmod sets easier, especially for
// implementing Map.values() and such.
// */
// abstract class AbstractUnmodCollection implements UnmodCollection {
// @SuppressWarnings("unchecked")
// @Override public boolean equals(Object other) {
// if (this == other) { return true; }
// if ( !(other instanceof Collection) ) { return false; }
// Collection that = (Collection) other;
// if (size() != that.size()) { return false; }
//
// // A set may contain all the elements of a list, plus additional elements, and have the
// // same size as a list that contains duplicates. Equality for lists and
// // sets is not the same. Lists are ordered and have duplicates. Sets have no duplicates
// // and may or may not be ordered.
// //
// // The only place that a Collection is returned and needs to live with an equals method
// // is on Map.values(). It can contain duplicates, so it's not a set. It can be ordered
// // (as in SortedMap.values()) which could equal a List, or unordered (just Map.values())
// // which can't be a Set because it needs to contain duplicates. Ugh, that one method
// // is an abomination and should not exist. If only Map had implemented Iterable
// // none of this would have been necessary.
// //
// // In order to have reflexive equals, check first for legitimate child interfaces
// // and let the other object compare itself to this one. I don't like the idea of
// // saying, "Are we equal? I don't know. What do you think?" because another class
// // could do the same thing and go into an infinite call loop (trampoline loop?).
// // So even though this is maybe unordered, we'll compare the random ordering to the
// // list.
// //
// // Hmm... Maybe there is no java.util.AbstractCollection because there is no sensible
// // way to implement it. Ditto why java.util.Map.values() doesn't implement equals() or
// // hashCode().
//
// // I can't imagine why containsAll would ever call equals on the parent collection,
// // so this should be safe from infinite call loops.
//
// // Doing containsAll() both ways should ensure that duplicates are checked properly
// // without checking order, but it's going to likely be a little slow. You want fast?
// // Implement List or Set instead!
// return containsAll(that) && that.containsAll(this);
// }
//
// @Override public int hashCode() { return UnmodIterable.hashCode(this); }
// }
// ========================================= Instance =========================================
// Methods are listed in the same order as the javadocs.
/** Not allowed - this is supposed to be unmodifiable */
@Override @Deprecated default boolean add(E e) {
throw new UnsupportedOperationException("Modification attempted");
}
/** Not allowed - this is supposed to be unmodifiable */
@Override @Deprecated default boolean addAll(Collection extends E> c) {
throw new UnsupportedOperationException("Modification attempted");
}
/** Not allowed - this is supposed to be unmodifiable */
@Override @Deprecated default void clear() {
throw new UnsupportedOperationException("Modification attempted");
}
// I don't think that this should be implemented here. It's a core function so each implementation
// of the interface should implement it
// /**
// This is quick for sets O(1) or O(log n), but slow for Lists O(n).
//
// {@inheritDoc}
// */
// @Override default boolean contains(Object o) {
// for (Object item : this) {
// if (Objects.equals(item, o)) { return true; }
// }
// return false;
// }
/**
The default implementation of this method has O(this.size() + that.size()) or O(n) performance.
So even though contains() is impossible to implement efficiently for Lists, containsAll()
has a decent implementation (brute force would be O(this.size() * that.size()) or O(n^2) ).
{@inheritDoc}
*/
@Override default boolean containsAll(Collection> c) {
// Faster to create a HashSet and call containsAll on that because it's
// O(this size PLUS that size), whereas looping through both would be
// O(this size TIMES that size).
return ( (c == null) || (c.size() < 1) ) ? true :
(size() < 1) ? false :
// (ts instanceof Set) ? ((Set) ts).containsAll(c) :
// (ts instanceof Map) ? ((Map) ts).entrySet().containsAll(c) :
new HashSet<>(this).containsAll(c);
}
// You can't implement equals correctly for a Collection due to duplicates, ordering, and
// the fact that List.equals(other) and Set.equals(other) both return false when other is
// not an instance of List or Set. This interface just isn't meant to be instantiated.
//boolean equals(Object o)
//int hashCode()
/** {@inheritDoc} */
@Override default boolean isEmpty() { return size() == 0; }
/** An unmodifiable iterator {@inheritDoc} */
@Override
UnmodIterator iterator();
//default Stream parallelStream()
/** Not allowed - this is supposed to be unmodifiable */
@Override @Deprecated default boolean remove(Object o) {
throw new UnsupportedOperationException("Modification attempted");
}
/** Not allowed - this is supposed to be unmodifiable */
@Override @Deprecated default boolean removeAll(Collection> c) {
throw new UnsupportedOperationException("Modification attempted");
}
/** Not allowed - this is supposed to be unmodifiable */
@Override @Deprecated default boolean removeIf(Predicate super E> filter) {
throw new UnsupportedOperationException("Modification attempted");
}
/** Not allowed - this is supposed to be unmodifiable */
@Override @Deprecated default boolean retainAll(Collection> c) {
throw new UnsupportedOperationException("Modification attempted");
}
//int size()
//default Spliterator spliterator()
//default Stream stream()
/**
* This method goes against Josh Bloch's Item 25: "Prefer Lists to Arrays", but is provided for backwards
* compatibility in some performance-critical situations. If you really need an array, consider using the somewhat
* type-safe version of this method instead, but read the caveats first.
*
* {@inheritDoc}
*/
@Override default Object[] toArray() {
return this.toArray(new Object[size()]);
}
/**
* This method goes against Josh Bloch's Item 25: "Prefer Lists to Arrays", but is provided for backwards
* compatibility in some performance-critical situations. If you need to create an array (you almost always do)
* then the best way to use this method is:
*
* MyThing[] things = col.toArray(new MyThing[coll.size()]);
*
* Calling this method any other way causes unnecessary work to be done - an extra memory allocation and potential
* garbage collection if the passed array is too small, extra effort to fill the end of the array with nulls if it
* is too large.
*
* {@inheritDoc}
*/
@SuppressWarnings("unchecked")
@Override default T[] toArray(T[] as) {
if (as.length < size()) {
as = (T[]) new Object[size()];
}
Iterator iter = iterator();
for (int i = 0; i < size(); i++) {
as[i] = (T) iter.next();
}
if (size() < as.length) {
Arrays.fill(as, size(), as.length, null);
}
return as;
}
}