UNPKG

graph-builder

Version:

A graph builder library for modeling abstract graph structures.

412 lines 17.8 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); /* * Copyright (C) 2007 The Guava Authors * * 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. * * Modifications (C) 2019 Ben Sorohan */ /** * A comparator, with additional methods to support common operations. This is an "enriched" version * of `Comparator` for pre-Java-8 users, in the same sense that {@link FluentIterable} is an * enriched {@link Iterable} for pre-Java-8 users. * * @remarks * * **Three types of methods** * * Like other fluent types, there are three types of methods present: methods for <i>acquiring</i>, * <i>chaining</i>, and <i>using</i>. * * <h4>Acquiring</h4> * * <p>The common ways to get an instance of `Ordering` are: * * <ul> * <li>Subclass it and implement {@link compare} instead of implementing {@link Comparator} * directly * <li>Pass a <i>pre-existing</i> {@link Comparator} instance to {@link from} * <li>Use the natural ordering, {@link Ordering.natural} * </ul> * * <h4>Chaining</h4> * * <p>Then you can use the <i>chaining</i> methods to get an altered version of that * `Ordering`, including: * * <ul> * <li>{@link reverse} * <li>{@link compound} * <li>{@link onResultOf} * <li>{@link nullsFirst} / {@link nullsLast} * </ul> * * <h4>Using</h4> * * <p>Finally, use the resulting `Ordering` anywhere a {@link Comparator} is required, or use * any of its special operations, such as: * * <ul> * <li>{@link immutableSortedCopy} * <li>{@link isOrdered} / {@link isStrictlyOrdered} * <li>{@link min} / {@link max} * </ul> * * **Understanding complex orderings** * * <p>Complex chained orderings like the following example can be challenging to understand. * * ```typescript * Ordering<Foo> ordering = * Ordering.natural() * .nullsFirst() * .onResultOf(getBarFunction) * .nullsLast(); * ``` * * Note that each chaining method returns a new ordering instance which is backed by the previous * instance, but has the chance to act on values <i>before</i> handing off to that backing instance. * As a result, it usually helps to read chained ordering expressions <i>backwards</i>. For example, * when `compare` is called on the above ordering: * * <ol> * <li>First, if only one `Foo` is null, that null value is treated as <i>greater</i> * <li>Next, non-null `Foo` values are passed to `getBarFunction` (we will be * comparing `Bar` values from now on) * <li>Next, if only one `Bar` is null, that null value is treated as <i>lesser</i> * <li>Finally, natural ordering is used (i.e. the result of `Bar.compareTo(Bar)` is * returned) * </ol> * * <p>Alas, {@link reverse} is a little different. As you read backwards through a chain and * encounter a call to `reverse`, continue working backwards until a result is determined, and * then reverse that result. * * **Additional notes** * * <p>Except as noted, the orderings returned by the factory methods of this class are serializable * if and only if the provided instances that back them are. For example, if `ordering` and * `function` can themselves be serialized, then `ordering.onResultOf(function)` can as * well. * * **For Java 8 users** * * <p>If you are using Java 8, this class is now obsolete. Most of its functionality is now provided * by {@link java.util.stream.Stream Stream} and by {@link Comparator} itself, and the rest can now * be found as static methods in our new {@link Comparators} class. See each method below for * further instructions. Whenever possible, you should change any references of type * `Ordering` to be of type `Comparator` instead. However, at this time we have no plan to * <i>deprecate</i> this class. * * <p>Many replacements involve adopting `Stream`, and these changes can sometimes make your * code verbose. Whenever following this advice, you should check whether `Stream` could be * adopted more comprehensively in your code; the end result may be quite a bit simpler. * * **See also** * * <p>See the Guava User Guide article on <a href= * "https://github.com/google/guava/wiki/OrderingExplained">`Ordering`</a>. */ class Ordering { /** * Returns the least of the specified values according to this ordering. If there are multiple * least values, the first of those is returned. The iterator will be left exhausted: its * `hasNext` method will return `false`. * * <p><b>Java 8 users:</b> Continue to use this method for now. After the next release of Guava, * use `Streams.stream(iterator).min(thisComparator).get()` instead (but note that it does * not guarantee which tied minimum element is returned). * * @param iterator the iterator whose minimum element is to be determined * throws NoSuchElementException if `iterator` is empty * throws ClassCastException if the parameters are not <i>mutually comparable</i> under this * ordering. */ min(iterator) { let result = iterator.next(); let minSoFar = result.value; while (!result.done) { result = iterator.next(); minSoFar = this.minOf(minSoFar, result.value); } return minSoFar; } /** * Returns the lesser of the two values according to this ordering. If the values compare as 0, * the first is returned. * * <p><b>Implementation note:</b> this method is invoked by the default implementations of the * other `min` overloads, so overriding it will affect their behavior. * * <p><b>Java 8 users:</b> Use `Collections.min(Arrays.asList(a, b), thisComparator)` * instead (but note that it does not guarantee which tied minimum element is returned). * * @param a value to compare, returned if less than or equal to b. * @param b value to compare. * throws ClassCastException if the parameters are not <i>mutually comparable</i> under this * ordering. */ minOf(a, b) { return (this.compare(a, b) <= 0) ? a : b; } /** * Returns the greatest of the specified values according to this ordering. If there are multiple * greatest values, the first of those is returned. The iterator will be left exhausted: its * `hasNext()` method will return `false`. * * <p><b>Java 8 users:</b> Continue to use this method for now. After the next release of Guava, * use `Streams.stream(iterator).max(thisComparator).get()` instead (but note that it does * not guarantee which tied maximum element is returned). * * @param iterator the iterator whose maximum element is to be determined * throws NoSuchElementException if `iterator` is empty * throws ClassCastException if the parameters are not <i>mutually comparable</i> under this * ordering. */ max(iterator) { let result = iterator.next(); let maxSoFar = result.value; while (!result.done) { result = iterator.next(); maxSoFar = this.maxOf(maxSoFar, result.value); } return maxSoFar; } /** * Returns the greater of the two values according to this ordering. If the values compare as 0, * the first is returned. * * <p><b>Implementation note:</b> this method is invoked by the default implementations of the * other `max` overloads, so overriding it will affect their behavior. * * <p><b>Java 8 users:</b> Use `Collections.max(Arrays.asList(a, b), thisComparator)` * instead (but note that it does not guarantee which tied maximum element is returned). * * @param a value to compare, returned if greater than or equal to b. * @param b value to compare. * throws ClassCastException if the parameters are not <i>mutually comparable</i> under this * ordering. */ maxOf(a, b) { return (this.compare(a, b) >= 0) ? a : b; } /** * Returns the `k` least elements from the given iterator according to this ordering, in * order from least to greatest. If there are fewer than `k` elements present, all will be * included. * * <p>The implementation does not necessarily use a <i>stable</i> sorting algorithm; when multiple * elements are equivalent, it is undefined which will come first. * * <p><b>Java 8 users:</b> Continue to use this method for now. After the next release of Guava, * use `Streams.stream(iterator).collect(Comparators.least(k, thisComparator))` instead. * * @returns an immutable `RandomAccess` list of the `k` least elements in ascending * order * throws IllegalArgumentException if `k` is negative */ // public leastOf<E extends T>(iterator: Iterator<E>, k: number): Array<E> { // if (k == 0 || !iterator.hasNext()) { // return []; // } else { // TopKSelector<E> selector = TopKSelector.least(k, this); // selector.offerAll(iterator); // return selector.topK(); // } // } /** * Returns the `k` greatest elements of the given iterable according to this ordering, in * order from greatest to least. If there are fewer than `k` elements present, all will be * included. * * <p>The implementation does not necessarily use a <i>stable</i> sorting algorithm; when multiple * elements are equivalent, it is undefined which will come first. * * @returns an immutable `RandomAccess` list of the `k` greatest elements in * <i>descending order</i> * throws IllegalArgumentException if `k` is negative */ // public <E extends T> List<E> greatestOf(Iterable<E> iterable, int k) { // // TODO(kevinb): see if delegation is hurting performance noticeably // // TODO(kevinb): if we change this implementation, add full unit tests. // return reverse().leastOf(iterable, k); // } /** * Returns the `k` greatest elements from the given iterator according to this ordering, in * order from greatest to least. If there are fewer than `k` elements present, all will be * included. * * <p>The implementation does not necessarily use a <i>stable</i> sorting algorithm; when multiple * elements are equivalent, it is undefined which will come first. * * <p><b>Java 8 users:</b> Continue to use this method for now. After the next release of Guava, * use `Streams.stream(iterator).collect(Comparators.greatest(k, thisComparator))` instead. * * @returns an immutable `RandomAccess` list of the `k` greatest elements in * <i>descending order</i> * throws IllegalArgumentException if `k` is negative */ // public <E extends T> List<E> greatestOf(Iterator<E> iterator, int k) { // return reverse().leastOf(iterator, k); // } /** * Returns a <b>mutable</b> list containing `elements` sorted by this ordering; use this * only when the resulting list may need further modification, or may contain `null`. The * input is not modified. The returned list is serializable and has random access. * * <p>Unlike {@link Sets.newTreeSet}, this method does not discard elements that are * duplicates according to the comparator. The sort performed is <i>stable</i>, meaning that such * elements will appear in the returned list in the same order they appeared in `elements`. * * <p><b>Performance note:</b> According to our * benchmarking * on Open JDK 7, {@link immutableSortedCopy} generally performs better (in both time and space) * than this method, and this method in turn generally performs better than copying the list and * calling {@link Collections.sort}. */ // TODO(kevinb): rerun benchmarks including new options // @CanIgnoreReturnValue // TODO(kak): Consider removing this // public <E extends T> List<E> sortedCopy(Iterable<E> elements) { // @SuppressWarnings("unchecked") // does not escape, and contains only E's // E[] array = (E[]) Iterables.toArray(elements); // Arrays.sort(array, this); // return Lists.newArrayList(Arrays.asList(array)); // } /** * Returns an <b>immutable</b> list containing `elements` sorted by this ordering. The input * is not modified. * * <p>Unlike {@link Sets.newTreeSet}, this method does not discard elements that are * duplicates according to the comparator. The sort performed is <i>stable</i>, meaning that such * elements will appear in the returned list in the same order they appeared in `elements`. * * <p><b>Performance note:</b> According to our * benchmarking * on Open JDK 7, this method is the most efficient way to make a sorted copy of a collection. * * throws NullPointerException if any element of `elements` is `null` */ // TODO(kevinb): rerun benchmarks including new options // @CanIgnoreReturnValue // TODO(kak): Consider removing this before internal migration // public <E extends T> ImmutableList<E> immutableSortedCopy(Iterable<E> elements) { // return ImmutableList.sortedCopyOf(this, elements); // } /** * Returns `true` if each element in `iterable` after the first is greater than or * equal to the element that preceded it, according to this ordering. Note that this is always * true when the iterable has fewer than two elements. * * <p><b>Java 8 users:</b> Use the equivalent {@link Comparators.isInOrder} * instead, since the rest of `Ordering` is mostly obsolete (as explained in the class * documentation). */ isOrdered(iterator) { let prev = iterator.next(); let next = iterator.next(); if (!next.done) { while (!next.done) { if (this.compare(prev.value, next.value) > 0) { return false; } prev = next; next = iterator.next(); } } return true; } /** * Returns `true` if each element in `iterable` after the first is <i>strictly</i> * greater than the element that preceded it, according to this ordering. Note that this is always * true when the iterable has fewer than two elements. * * <p><b>Java 8 users:</b> Use the equivalent {@link Comparators.isInStrictOrder(Iterable, * Comparator)} instead, since the rest of `Ordering` is mostly obsolete (as explained in * the class documentation). */ isStrictlyOrdered(iterator) { let prev = iterator.next(); let next = iterator.next(); if (!next.done) { while (!next.done) { if (this.compare(prev.value, next.value) >= 0) { return false; } prev = next; next = iterator.next(); } } return true; } } exports.Ordering = Ordering; // private static class ArbitraryOrderingHolder { // static final Ordering<Object> ARBITRARY_ORDERING = new ArbitraryOrdering(); // } // @VisibleForTesting // static class ArbitraryOrdering extends Ordering<Object> { // private final AtomicInteger counter = new AtomicInteger(0); // private final ConcurrentMap<Object, Integer> uids = // Platform.tryWeakKeys(new MapMaker()).makeMap(); // private Integer getUid(Object obj) { // Integer uid = uids.get(obj); // if (uid == null) { // // One or more integer values could be skipped in the event of a race // // to generate a UID for the same object from multiple threads, but // // that shouldn't be a problem. // uid = counter.getAndIncrement(); // Integer alreadySet = uids.putIfAbsent(obj, uid); // if (alreadySet != null) { // uid = alreadySet; // } // } // return uid; // } // @Override // public int compare(Object left, Object right) { // if (left == right) { // return 0; // } else if (left == null) { // return -1; // } else if (right == null) { // return 1; // } // int leftCode = identityHashCode(left); // int rightCode = identityHashCode(right); // if (leftCode != rightCode) { // return leftCode < rightCode ? -1 : 1; // } // // identityHashCode collision (rare, but not as rare as you'd think) // int result = getUid(left).compareTo(getUid(right)); // if (result == 0) { // throw new AssertionError(); // extremely, extremely unlikely. // } // return result; // } // @Override // public String toString() { // return "Ordering.arbitrary()"; // } // /* // * We need to be able to mock identityHashCode() calls for tests, because it // * can take 1-10 seconds to find colliding objects. Mocking frameworks that // * can do magic to mock static method calls still can't do so for a system // * class, so we need the indirection. In production, Hotspot should still // * recognize that the call is 1-morphic and should still be willing to // * inline it if necessary. // */ // int identityHashCode(Object object) { // return System.identityHashCode(object); // } // } //# sourceMappingURL=Ordering.js.map