All Downloads are FREE. Search and download functionalities are using the official Maven repository.

javaslang.collection.LinkedHashSet Maven / Gradle / Ivy

There is a newer version: 0.2.5
Show newest version
/*     / \____  _    _  ____   ______  / \ ____  __    _______
 *    /  /    \/ \  / \/    \ /  /\__\/  //    \/  \  //  /\__\   JΛVΛSLΛNG
 *  _/  /  /\  \  \/  /  /\  \\__\\  \  //  /\  \ /\\/ \ /__\ \   Copyright 2014-2016 Javaslang, http://javaslang.io
 * /___/\_/  \_/\____/\_/  \_/\__\/__/\__\_/  \_//  \__/\_____/   Licensed under the Apache License, Version 2.0
 */
package javaslang.collection;

import javaslang.*;
import javaslang.control.Option;

import java.io.*;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.NoSuchElementException;
import java.util.Objects;
import java.util.function.*;
import java.util.stream.Collector;

/**
 * An immutable {@code HashSet} implementation.
 *
 * @param  Component type
 * @author Ruslan Sennov, Patryk Najda, Daniel Dietrich
 * @since 2.0.0
 */
public final class LinkedHashSet implements Kind1, T>, Set, Serializable {

    private static final long serialVersionUID = 1L;

    private static final LinkedHashSet EMPTY = new LinkedHashSet<>(LinkedHashMap.empty());

    private final LinkedHashMap map;

    private LinkedHashSet(LinkedHashMap map) {
        this.map = map;
    }

    @SuppressWarnings("unchecked")
    public static  LinkedHashSet empty() {
        return (LinkedHashSet) EMPTY;
    }

    /**
     * Returns a {@link Collector} which may be used in conjunction with
     * {@link java.util.stream.Stream#collect(Collector)} to obtain a {@link LinkedHashSet}.
     *
     * @param  Component type of the LinkedHashSet.
     * @return A javaslang.collection.LinkedHashSet Collector.
     */
    public static  Collector, LinkedHashSet> collector() {
        final Supplier> supplier = ArrayList::new;
        final BiConsumer, T> accumulator = ArrayList::add;
        final BinaryOperator> combiner = (left, right) -> {
            left.addAll(right);
            return left;
        };
        final Function, LinkedHashSet> finisher = LinkedHashSet::ofAll;
        return Collector.of(supplier, accumulator, combiner, finisher);
    }

    /**
     * Narrows a widened {@code LinkedHashSet} to {@code LinkedHashSet}
     * by performing a type safe-cast. This is eligible because immutable/read-only
     * collections are covariant.
     *
     * @param linkedHashSet A {@code LinkedHashSet}.
     * @param            Component type of the {@code linkedHashSet}.
     * @return the given {@code linkedHashSet} instance as narrowed type {@code LinkedHashSet}.
     */
    @SuppressWarnings("unchecked")
    public static  LinkedHashSet narrow(LinkedHashSet linkedHashSet) {
        return (LinkedHashSet) linkedHashSet;
    }

    /**
     * Returns a singleton {@code LinkedHashSet}, i.e. a {@code LinkedHashSet} of one element.
     *
     * @param element An element.
     * @param      The component type
     * @return A new LinkedHashSet instance containing the given element
     */
    public static  LinkedHashSet of(T element) {
        return LinkedHashSet. empty().add(element);
    }

    /**
     * Creates a LinkedHashSet of the given elements.
     *
     * 
LinkedHashSet.of(1, 2, 3, 4)
* * @param Component type of the LinkedHashSet. * @param elements Zero or more elements. * @return A set containing the given elements. * @throws NullPointerException if {@code elements} is null */ @SafeVarargs public static LinkedHashSet of(T... elements) { Objects.requireNonNull(elements, "elements is null"); LinkedHashMap map = LinkedHashMap.empty(); for (T element : elements) { map = map.put(element, element); } return map.isEmpty() ? LinkedHashSet.empty() : new LinkedHashSet<>(map); } /** * Returns a LinkedHashSet containing {@code n} values of a given Function {@code f} * over a range of integer values from 0 to {@code n - 1}. * * @param Component type of the LinkedHashSet * @param n The number of elements in the LinkedHashSet * @param f The Function computing element values * @return A LinkedHashSet consisting of elements {@code f(0),f(1), ..., f(n - 1)} * @throws NullPointerException if {@code f} is null */ public static LinkedHashSet tabulate(int n, Function f) { Objects.requireNonNull(f, "f is null"); return Collections.tabulate(n, f, LinkedHashSet.empty(), LinkedHashSet::of); } /** * Returns a LinkedHashSet containing {@code n} values supplied by a given Supplier {@code s}. * * @param Component type of the LinkedHashSet * @param n The number of elements in the LinkedHashSet * @param s The Supplier computing element values * @return A LinkedHashSet of size {@code n}, where each element contains the result supplied by {@code s}. * @throws NullPointerException if {@code s} is null */ public static LinkedHashSet fill(int n, Supplier s) { Objects.requireNonNull(s, "s is null"); return Collections.fill(n, s, LinkedHashSet.empty(), LinkedHashSet::of); } /** * Creates a LinkedHashSet of the given elements. * * @param elements Set elements * @param The value type * @return A new LinkedHashSet containing the given entries */ @SuppressWarnings("unchecked") public static LinkedHashSet ofAll(Iterable elements) { Objects.requireNonNull(elements, "elements is null"); if (elements instanceof LinkedHashSet) { return (LinkedHashSet) elements; } else { final LinkedHashMap mao = addAll(LinkedHashMap.empty(), elements); return mao.isEmpty() ? empty() : new LinkedHashSet<>(mao); } } /** * Creates a LinkedHashSet based on the elements of a boolean array. * * @param array a boolean array * @return A new LinkedHashSet of Boolean values */ public static LinkedHashSet ofAll(boolean[] array) { Objects.requireNonNull(array, "array is null"); return LinkedHashSet.ofAll(Iterator.ofAll(array)); } /** * Creates a LinkedHashSet based on the elements of a byte array. * * @param array a byte array * @return A new LinkedHashSet of Byte values */ public static LinkedHashSet ofAll(byte[] array) { Objects.requireNonNull(array, "array is null"); return LinkedHashSet.ofAll(Iterator.ofAll(array)); } /** * Creates a LinkedHashSet based on the elements of a char array. * * @param array a char array * @return A new LinkedHashSet of Character values */ public static LinkedHashSet ofAll(char[] array) { Objects.requireNonNull(array, "array is null"); return LinkedHashSet.ofAll(Iterator.ofAll(array)); } /** * Creates a LinkedHashSet based on the elements of a double array. * * @param array a double array * @return A new LinkedHashSet of Double values */ public static LinkedHashSet ofAll(double[] array) { Objects.requireNonNull(array, "array is null"); return LinkedHashSet.ofAll(Iterator.ofAll(array)); } /** * Creates a LinkedHashSet based on the elements of a float array. * * @param array a float array * @return A new LinkedHashSet of Float values */ public static LinkedHashSet ofAll(float[] array) { Objects.requireNonNull(array, "array is null"); return LinkedHashSet.ofAll(Iterator.ofAll(array)); } /** * Creates a LinkedHashSet based on the elements of an int array. * * @param array an int array * @return A new LinkedHashSet of Integer values */ public static LinkedHashSet ofAll(int[] array) { Objects.requireNonNull(array, "array is null"); return LinkedHashSet.ofAll(Iterator.ofAll(array)); } /** * Creates a LinkedHashSet based on the elements of a long array. * * @param array a long array * @return A new LinkedHashSet of Long values */ public static LinkedHashSet ofAll(long[] array) { Objects.requireNonNull(array, "array is null"); return LinkedHashSet.ofAll(Iterator.ofAll(array)); } /** * Creates a LinkedHashSet based on the elements of a short array. * * @param array a short array * @return A new LinkedHashSet of Short values */ public static LinkedHashSet ofAll(short[] array) { Objects.requireNonNull(array, "array is null"); return LinkedHashSet.ofAll(Iterator.ofAll(array)); } /** * Creates a LinkedHashSet of int numbers starting from {@code from}, extending to {@code toExclusive - 1}. *

* Examples: *

     * 
     * LinkedHashSet.range(0, 0)  // = LinkedHashSet()
     * LinkedHashSet.range(2, 0)  // = LinkedHashSet()
     * LinkedHashSet.range(-2, 2) // = LinkedHashSet(-2, -1, 0, 1)
     * 
     * 
* * @param from the first number * @param toExclusive the last number + 1 * @return a range of int values as specified or the empty range if {@code from >= toExclusive} */ public static LinkedHashSet range(int from, int toExclusive) { return LinkedHashSet.ofAll(Iterator.range(from, toExclusive)); } public static LinkedHashSet range(char from, char toExclusive) { return LinkedHashSet.ofAll(Iterator.range(from, toExclusive)); } /** * Creates a LinkedHashSet of int numbers starting from {@code from}, extending to {@code toExclusive - 1}, * with {@code step}. *

* Examples: *

     * 
     * LinkedHashSet.rangeBy(1, 3, 1)  // = LinkedHashSet(1, 2)
     * LinkedHashSet.rangeBy(1, 4, 2)  // = LinkedHashSet(1, 3)
     * LinkedHashSet.rangeBy(4, 1, -2) // = LinkedHashSet(4, 2)
     * LinkedHashSet.rangeBy(4, 1, 2)  // = LinkedHashSet()
     * 
     * 
* * @param from the first number * @param toExclusive the last number + 1 * @param step the step * @return a range of long values as specified or the empty range if
* {@code from >= toInclusive} and {@code step > 0} or
* {@code from <= toInclusive} and {@code step < 0} * @throws IllegalArgumentException if {@code step} is zero */ public static LinkedHashSet rangeBy(int from, int toExclusive, int step) { return LinkedHashSet.ofAll(Iterator.rangeBy(from, toExclusive, step)); } public static LinkedHashSet rangeBy(char from, char toExclusive, int step) { return LinkedHashSet.ofAll(Iterator.rangeBy(from, toExclusive, step)); } public static LinkedHashSet rangeBy(double from, double toExclusive, double step) { return LinkedHashSet.ofAll(Iterator.rangeBy(from, toExclusive, step)); } /** * Creates a LinkedHashSet of long numbers starting from {@code from}, extending to {@code toExclusive - 1}. *

* Examples: *

     * 
     * LinkedHashSet.range(0L, 0L)  // = LinkedHashSet()
     * LinkedHashSet.range(2L, 0L)  // = LinkedHashSet()
     * LinkedHashSet.range(-2L, 2L) // = LinkedHashSet(-2L, -1L, 0L, 1L)
     * 
     * 
* * @param from the first number * @param toExclusive the last number + 1 * @return a range of long values as specified or the empty range if {@code from >= toExclusive} */ public static LinkedHashSet range(long from, long toExclusive) { return LinkedHashSet.ofAll(Iterator.range(from, toExclusive)); } /** * Creates a LinkedHashSet of long numbers starting from {@code from}, extending to {@code toExclusive - 1}, * with {@code step}. *

* Examples: *

     * 
     * LinkedHashSet.rangeBy(1L, 3L, 1L)  // = LinkedHashSet(1L, 2L)
     * LinkedHashSet.rangeBy(1L, 4L, 2L)  // = LinkedHashSet(1L, 3L)
     * LinkedHashSet.rangeBy(4L, 1L, -2L) // = LinkedHashSet(4L, 2L)
     * LinkedHashSet.rangeBy(4L, 1L, 2L)  // = LinkedHashSet()
     * 
     * 
* * @param from the first number * @param toExclusive the last number + 1 * @param step the step * @return a range of long values as specified or the empty range if
* {@code from >= toInclusive} and {@code step > 0} or
* {@code from <= toInclusive} and {@code step < 0} * @throws IllegalArgumentException if {@code step} is zero */ public static LinkedHashSet rangeBy(long from, long toExclusive, long step) { return LinkedHashSet.ofAll(Iterator.rangeBy(from, toExclusive, step)); } /** * Creates a LinkedHashSet of int numbers starting from {@code from}, extending to {@code toInclusive}. *

* Examples: *

     * 
     * LinkedHashSet.rangeClosed(0, 0)  // = LinkedHashSet(0)
     * LinkedHashSet.rangeClosed(2, 0)  // = LinkedHashSet()
     * LinkedHashSet.rangeClosed(-2, 2) // = LinkedHashSet(-2, -1, 0, 1, 2)
     * 
     * 
* * @param from the first number * @param toInclusive the last number * @return a range of int values as specified or the empty range if {@code from > toInclusive} */ public static LinkedHashSet rangeClosed(int from, int toInclusive) { return LinkedHashSet.ofAll(Iterator.rangeClosed(from, toInclusive)); } public static LinkedHashSet rangeClosed(char from, char toInclusive) { return LinkedHashSet.ofAll(Iterator.rangeClosed(from, toInclusive)); } /** * Creates a LinkedHashSet of int numbers starting from {@code from}, extending to {@code toInclusive}, * with {@code step}. *

* Examples: *

     * 
     * LinkedHashSet.rangeClosedBy(1, 3, 1)  // = LinkedHashSet(1, 2, 3)
     * LinkedHashSet.rangeClosedBy(1, 4, 2)  // = LinkedHashSet(1, 3)
     * LinkedHashSet.rangeClosedBy(4, 1, -2) // = LinkedHashSet(4, 2)
     * LinkedHashSet.rangeClosedBy(4, 1, 2)  // = LinkedHashSet()
     * 
     * 
* * @param from the first number * @param toInclusive the last number * @param step the step * @return a range of int values as specified or the empty range if
* {@code from > toInclusive} and {@code step > 0} or
* {@code from < toInclusive} and {@code step < 0} * @throws IllegalArgumentException if {@code step} is zero */ public static LinkedHashSet rangeClosedBy(int from, int toInclusive, int step) { return LinkedHashSet.ofAll(Iterator.rangeClosedBy(from, toInclusive, step)); } public static LinkedHashSet rangeClosedBy(char from, char toInclusive, int step) { return LinkedHashSet.ofAll(Iterator.rangeClosedBy(from, toInclusive, step)); } public static LinkedHashSet rangeClosedBy(double from, double toInclusive, double step) { return LinkedHashSet.ofAll(Iterator.rangeClosedBy(from, toInclusive, step)); } /** * Creates a LinkedHashSet of long numbers starting from {@code from}, extending to {@code toInclusive}. *

* Examples: *

     * 
     * LinkedHashSet.rangeClosed(0L, 0L)  // = LinkedHashSet(0L)
     * LinkedHashSet.rangeClosed(2L, 0L)  // = LinkedHashSet()
     * LinkedHashSet.rangeClosed(-2L, 2L) // = LinkedHashSet(-2L, -1L, 0L, 1L, 2L)
     * 
     * 
* * @param from the first number * @param toInclusive the last number * @return a range of long values as specified or the empty range if {@code from > toInclusive} */ public static LinkedHashSet rangeClosed(long from, long toInclusive) { return LinkedHashSet.ofAll(Iterator.rangeClosed(from, toInclusive)); } /** * Creates a LinkedHashSet of long numbers starting from {@code from}, extending to {@code toInclusive}, * with {@code step}. *

* Examples: *

     * 
     * LinkedHashSet.rangeClosedBy(1L, 3L, 1L)  // = LinkedHashSet(1L, 2L, 3L)
     * LinkedHashSet.rangeClosedBy(1L, 4L, 2L)  // = LinkedHashSet(1L, 3L)
     * LinkedHashSet.rangeClosedBy(4L, 1L, -2L) // = LinkedHashSet(4L, 2L)
     * LinkedHashSet.rangeClosedBy(4L, 1L, 2L)  // = LinkedHashSet()
     * 
     * 
* * @param from the first number * @param toInclusive the last number * @param step the step * @return a range of int values as specified or the empty range if
* {@code from > toInclusive} and {@code step > 0} or
* {@code from < toInclusive} and {@code step < 0} * @throws IllegalArgumentException if {@code step} is zero */ public static LinkedHashSet rangeClosedBy(long from, long toInclusive, long step) { return LinkedHashSet.ofAll(Iterator.rangeClosedBy(from, toInclusive, step)); } @Override public LinkedHashSet add(T element) { return new LinkedHashSet<>(map.put(element, element)); } @Override public LinkedHashSet addAll(Iterable elements) { Objects.requireNonNull(elements, "elements is null"); final LinkedHashMap that = addAll(map, elements); if (that.size() == map.size()) { return this; } else { return new LinkedHashSet<>(that); } } @Override public boolean contains(T element) { return map.get(element).isDefined(); } @Override public LinkedHashSet diff(Set elements) { Objects.requireNonNull(elements, "elements is null"); if (isEmpty() || elements.isEmpty()) { return this; } else { return removeAll(elements); } } @Override public LinkedHashSet distinct() { return this; } @Override public LinkedHashSet distinctBy(Comparator comparator) { Objects.requireNonNull(comparator, "comparator is null"); return LinkedHashSet.ofAll(iterator().distinctBy(comparator)); } @Override public LinkedHashSet distinctBy(Function keyExtractor) { Objects.requireNonNull(keyExtractor, "keyExtractor is null"); return LinkedHashSet.ofAll(iterator().distinctBy(keyExtractor)); } @Override public LinkedHashSet drop(long n) { if (n <= 0) { return this; } else { return LinkedHashSet.ofAll(iterator().drop(n)); } } @Override public LinkedHashSet dropRight(long n) { if (n <= 0) { return this; } else { return LinkedHashSet.ofAll(iterator().dropRight(n)); } } @Override public LinkedHashSet dropUntil(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); return dropWhile(predicate.negate()); } @Override public LinkedHashSet dropWhile(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); final LinkedHashSet dropped = LinkedHashSet.ofAll(iterator().dropWhile(predicate)); return dropped.length() == length() ? this : dropped; } @Override public LinkedHashSet filter(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); final LinkedHashSet filtered = LinkedHashSet.ofAll(iterator().filter(predicate)); return filtered.length() == length() ? this : filtered; } @Override public LinkedHashSet flatMap(Function> mapper) { Objects.requireNonNull(mapper, "mapper is null"); if (isEmpty()) { return empty(); } else { final LinkedHashMap that = foldLeft(LinkedHashMap.empty(), (tree, t) -> addAll(tree, mapper.apply(t))); return new LinkedHashSet<>(that); } } @Override public U foldRight(U zero, BiFunction f) { Objects.requireNonNull(f, "f is null"); return iterator().foldRight(zero, f); } @Override public Map> groupBy(Function classifier) { return foldLeft(HashMap.empty(), (map, t) -> { final C key = classifier.apply(t); final LinkedHashSet values = map.get(key).map(ts -> ts.add(t)).getOrElse(LinkedHashSet.of(t)); return map.put(key, values); }); } @Override public Iterator> grouped(long size) { return sliding(size, size); } @Override public boolean hasDefiniteSize() { return true; } @Override public T head() { if (map.isEmpty()) { throw new NoSuchElementException("head of empty set"); } return iterator().next(); } @Override public Option headOption() { return iterator().headOption(); } @Override public LinkedHashSet init() { if (map.isEmpty()) { throw new UnsupportedOperationException("tail of empty set"); } else { return new LinkedHashSet<>(map.init()); } } @Override public Option> initOption() { return isEmpty() ? Option.none() : Option.some(init()); } @Override public LinkedHashSet intersect(Set elements) { Objects.requireNonNull(elements, "elements is null"); if (isEmpty() || elements.isEmpty()) { return empty(); } else { return retainAll(elements); } } @Override public boolean isEmpty() { return map.isEmpty(); } @Override public boolean isTraversableAgain() { return true; } @Override public Iterator iterator() { return map.iterator().map(t -> t._1); } @Override public int length() { return map.size(); } @Override public LinkedHashSet map(Function mapper) { Objects.requireNonNull(mapper, "mapper is null"); if (isEmpty()) { return empty(); } else { final LinkedHashMap that = foldLeft(LinkedHashMap.empty(), (tree, t) -> { final U u = mapper.apply(t); return tree.put(u, u); }); return new LinkedHashSet<>(that); } } @Override public String mkString(CharSequence prefix, CharSequence delimiter, CharSequence suffix) { return iterator().mkString(prefix, delimiter, suffix); } @Override public Tuple2, LinkedHashSet> partition(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); final Tuple2, Iterator> p = iterator().partition(predicate); return Tuple.of(LinkedHashSet.ofAll(p._1), LinkedHashSet.ofAll(p._2)); } @Override public LinkedHashSet peek(Consumer action) { Objects.requireNonNull(action, "action is null"); if (!isEmpty()) { action.accept(iterator().head()); } return this; } @Override public LinkedHashSet remove(T element) { final LinkedHashMap newMap = map.remove(element); return (newMap == map) ? this : new LinkedHashSet<>(newMap); } @Override public LinkedHashSet removeAll(Iterable elements) { Objects.requireNonNull(elements, "elements is null"); LinkedHashMap that = map; for (T element : elements) { that = that.remove(element); } return (that == map) ? this : new LinkedHashSet<>(that); } @Override public LinkedHashSet replace(T currentElement, T newElement) { if (!Objects.equals(currentElement, newElement) && contains(currentElement)) { final Tuple2 currentPair = Tuple.of(currentElement, currentElement); final Tuple2 newPair = Tuple.of(newElement, newElement); final LinkedHashMap newMap = map.replace(currentPair, newPair); return new LinkedHashSet<>(newMap); } else { return this; } } @Override public LinkedHashSet replaceAll(T currentElement, T newElement) { return replace(currentElement, newElement); } @Override public LinkedHashSet retainAll(Iterable elements) { Objects.requireNonNull(elements, "elements is null"); final LinkedHashMap kept = addAll(LinkedHashMap.empty(), elements); LinkedHashMap that = LinkedHashMap.empty(); for (T element : this) { if (kept.containsKey(element)) { that = that.put(element, element); } } return that.isEmpty() ? empty() : that.size() == size() ? this : new LinkedHashSet<>(that); } @Override public LinkedHashSet scan(T zero, BiFunction operation) { return scanLeft(zero, operation); } @Override public LinkedHashSet scanLeft(U zero, BiFunction operation) { Objects.requireNonNull(operation, "operation is null"); return Collections.scanLeft(this, zero, operation, new java.util.ArrayList<>(), (c, u) -> { c.add(u); return c; }, LinkedHashSet::ofAll); } @Override public LinkedHashSet scanRight(U zero, BiFunction operation) { Objects.requireNonNull(operation, "operation is null"); return Collections.scanRight(this, zero, operation, List.empty(), List::prepend, LinkedHashSet::ofAll); } @Override public Iterator> sliding(long size) { return sliding(size, 1); } @Override public Iterator> sliding(long size, long step) { return iterator().sliding(size, step).map(LinkedHashSet::ofAll); } @Override public Tuple2, LinkedHashSet> span(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); final Tuple2, Iterator> t = iterator().span(predicate); return Tuple.of(LinkedHashSet.ofAll(t._1), LinkedHashSet.ofAll(t._2)); } @Override public LinkedHashSet tail() { if (map.isEmpty()) { throw new UnsupportedOperationException("tail of empty set"); } return remove(head()); } @Override public Option> tailOption() { return isEmpty() ? Option.none() : Option.some(tail()); } @Override public LinkedHashSet take(long n) { if (map.size() <= n) { return this; } return LinkedHashSet.ofAll(() -> iterator().take(n)); } @Override public LinkedHashSet takeRight(long n) { if (map.size() <= n) { return this; } return LinkedHashSet.ofAll(() -> iterator().takeRight(n)); } @Override public LinkedHashSet takeUntil(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); return takeWhile(predicate.negate()); } @Override public LinkedHashSet takeWhile(Predicate predicate) { Objects.requireNonNull(predicate, "predicate is null"); LinkedHashSet taken = LinkedHashSet.ofAll(iterator().takeWhile(predicate)); return taken.length() == length() ? this : taken; } /** * Transforms this {@code LinkedHashSet}. * * @param f A transformation * @param Type of transformation result * @return An instance of type {@code U} * @throws NullPointerException if {@code f} is null */ public U transform(Function, ? extends U> f) { Objects.requireNonNull(f, "f is null"); return f.apply(this); } @Override public java.util.LinkedHashSet toJavaSet() { return toJavaSet(java.util.LinkedHashSet::new); } @SuppressWarnings("unchecked") @Override public LinkedHashSet union(Set elements) { Objects.requireNonNull(elements, "elements is null"); if (isEmpty()) { if (elements instanceof LinkedHashSet) { return (LinkedHashSet) elements; } else { return LinkedHashSet.ofAll(elements); } } else if (elements.isEmpty()) { return this; } else { final LinkedHashMap that = addAll(map, elements); if (that.size() == map.size()) { return this; } else { return new LinkedHashSet<>(that); } } } @Override public Tuple2, LinkedHashSet> unzip( Function> unzipper) { Objects.requireNonNull(unzipper, "unzipper is null"); Tuple2, Iterator> t = iterator().unzip(unzipper); return Tuple.of(LinkedHashSet.ofAll(t._1), LinkedHashSet.ofAll(t._2)); } @Override public Tuple3, LinkedHashSet, LinkedHashSet> unzip3( Function> unzipper) { Objects.requireNonNull(unzipper, "unzipper is null"); Tuple3, Iterator, Iterator> t = iterator().unzip3(unzipper); return Tuple.of(LinkedHashSet.ofAll(t._1), LinkedHashSet.ofAll(t._2), LinkedHashSet.ofAll(t._3)); } @Override public LinkedHashSet> zip(Iterable that) { Objects.requireNonNull(that, "that is null"); return LinkedHashSet.ofAll(iterator().zip(that)); } @Override public LinkedHashSet> zipAll(Iterable that, T thisElem, U thatElem) { Objects.requireNonNull(that, "that is null"); return LinkedHashSet.ofAll(iterator().zipAll(that, thisElem, thatElem)); } @Override public LinkedHashSet> zipWithIndex() { return LinkedHashSet.ofAll(iterator().zipWithIndex()); } // -- Object @Override public int hashCode() { return map.hashCode(); } @SuppressWarnings("unchecked") @Override public boolean equals(Object o) { if (o == this) { return true; } else if (o instanceof LinkedHashSet) { final LinkedHashSet that = (LinkedHashSet) o; return this.map.equals(that.map); } else { return false; } } @Override public String stringPrefix() { return "LinkedHashSet"; } @Override public String toString() { return mkString(stringPrefix() + "(", ", ", ")"); } private static LinkedHashMap addAll(LinkedHashMap initial, Iterable additional) { LinkedHashMap that = initial; for (T t : additional) { that = that.put(t, t); } return that; } // -- Serialization /** * {@code writeReplace} method for the serialization proxy pattern. *

* The presence of this method causes the serialization system to emit a SerializationProxy instance instead of * an instance of the enclosing class. * * @return A SerialiationProxy for this enclosing class. */ private Object writeReplace() { return new SerializationProxy<>(this.map); } /** * {@code readObject} method for the serialization proxy pattern. *

* Guarantees that the serialization system will never generate a serialized instance of the enclosing class. * * @param stream An object serialization stream. * @throws InvalidObjectException This method will throw with the message "Proxy required". */ private void readObject(ObjectInputStream stream) throws InvalidObjectException { throw new InvalidObjectException("Proxy required"); } /** * A serialization proxy which, in this context, is used to deserialize immutable, linked Lists with final * instance fields. * * @param The component type of the underlying list. */ // DEV NOTE: The serialization proxy pattern is not compatible with non-final, i.e. extendable, // classes. Also, it may not be compatible with circular object graphs. private static final class SerializationProxy implements Serializable { private static final long serialVersionUID = 1L; // the instance to be serialized/deserialized private transient LinkedHashMap map; /** * Constructor for the case of serialization, called by {@link LinkedHashSet#writeReplace()}. *

* The constructor of a SerializationProxy takes an argument that concisely represents the logical state of * an instance of the enclosing class. * * @param map a Cons */ SerializationProxy(LinkedHashMap map) { this.map = map; } /** * Write an object to a serialization stream. * * @param s An object serialization stream. * @throws IOException If an error occurs writing to the stream. */ private void writeObject(ObjectOutputStream s) throws IOException { s.defaultWriteObject(); s.writeInt(map.size()); for (Tuple2 e : map) { s.writeObject(e._1); } } /** * Read an object from a deserialization stream. * * @param s An object deserialization stream. * @throws ClassNotFoundException If the object's class read from the stream cannot be found. * @throws InvalidObjectException If the stream contains no list elements. * @throws IOException If an error occurs reading from the stream. */ private void readObject(ObjectInputStream s) throws ClassNotFoundException, IOException { s.defaultReadObject(); final int size = s.readInt(); if (size < 0) { throw new InvalidObjectException("No elements"); } LinkedHashMap temp = LinkedHashMap.empty(); for (int i = 0; i < size; i++) { @SuppressWarnings("unchecked") final T element = (T) s.readObject(); temp = temp.put(element, element); } map = temp; } /** * {@code readResolve} method for the serialization proxy pattern. *

* Returns a logically equivalent instance of the enclosing class. The presence of this method causes the * serialization system to translate the serialization proxy back into an instance of the enclosing class * upon deserialization. * * @return A deserialized instance of the enclosing class. */ private Object readResolve() { return map.isEmpty() ? LinkedHashSet.empty() : new LinkedHashSet<>(map); } } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy