• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2008 The Guava Authors
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.google.common.collect;
18 
19 import static com.google.common.base.Preconditions.checkArgument;
20 import static com.google.common.base.Preconditions.checkNotNull;
21 import static com.google.common.collect.CollectPreconditions.checkNonnegative;
22 import static java.util.Objects.requireNonNull;
23 
24 import com.google.common.annotations.Beta;
25 import com.google.common.annotations.GwtCompatible;
26 import com.google.common.base.Function;
27 import com.google.common.base.Predicate;
28 import com.google.common.base.Predicates;
29 import com.google.common.math.IntMath;
30 import com.google.common.primitives.Ints;
31 import java.util.AbstractCollection;
32 import java.util.ArrayList;
33 import java.util.Arrays;
34 import java.util.Collection;
35 import java.util.Collections;
36 import java.util.Comparator;
37 import java.util.Iterator;
38 import java.util.List;
39 import javax.annotation.CheckForNull;
40 import org.checkerframework.checker.nullness.qual.Nullable;
41 
42 /**
43  * Provides static methods for working with {@code Collection} instances.
44  *
45  * <p><b>Java 8 users:</b> several common uses for this class are now more comprehensively addressed
46  * by the new {@link java.util.stream.Stream} library. Read the method documentation below for
47  * comparisons. These methods are not being deprecated, but we gently encourage you to migrate to
48  * streams.
49  *
50  * @author Chris Povirk
51  * @author Mike Bostock
52  * @author Jared Levy
53  * @since 2.0
54  */
55 @GwtCompatible
56 @ElementTypesAreNonnullByDefault
57 public final class Collections2 {
Collections2()58   private Collections2() {}
59 
60   /**
61    * Returns the elements of {@code unfiltered} that satisfy a predicate. The returned collection is
62    * a live view of {@code unfiltered}; changes to one affect the other.
63    *
64    * <p>The resulting collection's iterator does not support {@code remove()}, but all other
65    * collection methods are supported. When given an element that doesn't satisfy the predicate, the
66    * collection's {@code add()} and {@code addAll()} methods throw an {@link
67    * IllegalArgumentException}. When methods such as {@code removeAll()} and {@code clear()} are
68    * called on the filtered collection, only elements that satisfy the filter will be removed from
69    * the underlying collection.
70    *
71    * <p>The returned collection isn't threadsafe or serializable, even if {@code unfiltered} is.
72    *
73    * <p>Many of the filtered collection's methods, such as {@code size()}, iterate across every
74    * element in the underlying collection and determine which elements satisfy the filter. When a
75    * live view is <i>not</i> needed, it may be faster to copy {@code Iterables.filter(unfiltered,
76    * predicate)} and use the copy.
77    *
78    * <p><b>Warning:</b> {@code predicate} must be <i>consistent with equals</i>, as documented at
79    * {@link Predicate#apply}. Do not provide a predicate such as {@code
80    * Predicates.instanceOf(ArrayList.class)}, which is inconsistent with equals. (See {@link
81    * Iterables#filter(Iterable, Class)} for related functionality.)
82    *
83    * <p><b>{@code Stream} equivalent:</b> {@link java.util.stream.Stream#filter Stream.filter}.
84    */
85   // TODO(kevinb): how can we omit that Iterables link when building gwt
86   // javadoc?
filter( Collection<E> unfiltered, Predicate<? super E> predicate)87   public static <E extends @Nullable Object> Collection<E> filter(
88       Collection<E> unfiltered, Predicate<? super E> predicate) {
89     if (unfiltered instanceof FilteredCollection) {
90       // Support clear(), removeAll(), and retainAll() when filtering a filtered
91       // collection.
92       return ((FilteredCollection<E>) unfiltered).createCombined(predicate);
93     }
94 
95     return new FilteredCollection<E>(checkNotNull(unfiltered), checkNotNull(predicate));
96   }
97 
98   /**
99    * Delegates to {@link Collection#contains}. Returns {@code false} if the {@code contains} method
100    * throws a {@code ClassCastException} or {@code NullPointerException}.
101    */
safeContains(Collection<?> collection, @CheckForNull Object object)102   static boolean safeContains(Collection<?> collection, @CheckForNull Object object) {
103     checkNotNull(collection);
104     try {
105       return collection.contains(object);
106     } catch (ClassCastException | NullPointerException e) {
107       return false;
108     }
109   }
110 
111   /**
112    * Delegates to {@link Collection#remove}. Returns {@code false} if the {@code remove} method
113    * throws a {@code ClassCastException} or {@code NullPointerException}.
114    */
safeRemove(Collection<?> collection, @CheckForNull Object object)115   static boolean safeRemove(Collection<?> collection, @CheckForNull Object object) {
116     checkNotNull(collection);
117     try {
118       return collection.remove(object);
119     } catch (ClassCastException | NullPointerException e) {
120       return false;
121     }
122   }
123 
124   static class FilteredCollection<E extends @Nullable Object> extends AbstractCollection<E> {
125     final Collection<E> unfiltered;
126     final Predicate<? super E> predicate;
127 
FilteredCollection(Collection<E> unfiltered, Predicate<? super E> predicate)128     FilteredCollection(Collection<E> unfiltered, Predicate<? super E> predicate) {
129       this.unfiltered = unfiltered;
130       this.predicate = predicate;
131     }
132 
createCombined(Predicate<? super E> newPredicate)133     FilteredCollection<E> createCombined(Predicate<? super E> newPredicate) {
134       return new FilteredCollection<E>(unfiltered, Predicates.<E>and(predicate, newPredicate));
135       // .<E> above needed to compile in JDK 5
136     }
137 
138     @Override
add(@arametricNullness E element)139     public boolean add(@ParametricNullness E element) {
140       checkArgument(predicate.apply(element));
141       return unfiltered.add(element);
142     }
143 
144     @Override
addAll(Collection<? extends E> collection)145     public boolean addAll(Collection<? extends E> collection) {
146       for (E element : collection) {
147         checkArgument(predicate.apply(element));
148       }
149       return unfiltered.addAll(collection);
150     }
151 
152     @Override
clear()153     public void clear() {
154       Iterables.removeIf(unfiltered, predicate);
155     }
156 
157     @Override
contains(@heckForNull Object element)158     public boolean contains(@CheckForNull Object element) {
159       if (safeContains(unfiltered, element)) {
160         @SuppressWarnings("unchecked") // element is in unfiltered, so it must be an E
161         E e = (E) element;
162         return predicate.apply(e);
163       }
164       return false;
165     }
166 
167     @Override
containsAll(Collection<?> collection)168     public boolean containsAll(Collection<?> collection) {
169       return containsAllImpl(this, collection);
170     }
171 
172     @Override
isEmpty()173     public boolean isEmpty() {
174       return !Iterables.any(unfiltered, predicate);
175     }
176 
177     @Override
iterator()178     public Iterator<E> iterator() {
179       return Iterators.filter(unfiltered.iterator(), predicate);
180     }
181 
182     @Override
remove(@heckForNull Object element)183     public boolean remove(@CheckForNull Object element) {
184       return contains(element) && unfiltered.remove(element);
185     }
186 
187     @Override
removeAll(final Collection<?> collection)188     public boolean removeAll(final Collection<?> collection) {
189       boolean changed = false;
190       Iterator<E> itr = unfiltered.iterator();
191       while (itr.hasNext()) {
192         E e = itr.next();
193         if (predicate.apply(e) && collection.contains(e)) {
194           itr.remove();
195           changed = true;
196         }
197       }
198       return changed;
199     }
200 
201     @Override
retainAll(final Collection<?> collection)202     public boolean retainAll(final Collection<?> collection) {
203       boolean changed = false;
204       Iterator<E> itr = unfiltered.iterator();
205       while (itr.hasNext()) {
206         E e = itr.next();
207         if (predicate.apply(e) && !collection.contains(e)) {
208           itr.remove();
209           changed = true;
210         }
211       }
212       return changed;
213     }
214 
215     @Override
size()216     public int size() {
217       int size = 0;
218       for (E e : unfiltered) {
219         if (predicate.apply(e)) {
220           size++;
221         }
222       }
223       return size;
224     }
225 
226     @Override
toArray()227     public @Nullable Object[] toArray() {
228       // creating an ArrayList so filtering happens once
229       return Lists.newArrayList(iterator()).toArray();
230     }
231 
232     @Override
233     @SuppressWarnings("nullness") // b/192354773 in our checker affects toArray declarations
toArray(T[] array)234     public <T extends @Nullable Object> T[] toArray(T[] array) {
235       return Lists.newArrayList(iterator()).toArray(array);
236     }
237   }
238 
239   /**
240    * Returns a collection that applies {@code function} to each element of {@code fromCollection}.
241    * The returned collection is a live view of {@code fromCollection}; changes to one affect the
242    * other.
243    *
244    * <p>The returned collection's {@code add()} and {@code addAll()} methods throw an {@link
245    * UnsupportedOperationException}. All other collection methods are supported, as long as {@code
246    * fromCollection} supports them.
247    *
248    * <p>The returned collection isn't threadsafe or serializable, even if {@code fromCollection} is.
249    *
250    * <p>When a live view is <i>not</i> needed, it may be faster to copy the transformed collection
251    * and use the copy.
252    *
253    * <p>If the input {@code Collection} is known to be a {@code List}, consider {@link
254    * Lists#transform}. If only an {@code Iterable} is available, use {@link Iterables#transform}.
255    *
256    * <p><b>{@code Stream} equivalent:</b> {@link java.util.stream.Stream#map Stream.map}.
257    */
transform( Collection<F> fromCollection, Function<? super F, T> function)258   public static <F extends @Nullable Object, T extends @Nullable Object> Collection<T> transform(
259       Collection<F> fromCollection, Function<? super F, T> function) {
260     return new TransformedCollection<>(fromCollection, function);
261   }
262 
263   static class TransformedCollection<F extends @Nullable Object, T extends @Nullable Object>
264       extends AbstractCollection<T> {
265     final Collection<F> fromCollection;
266     final Function<? super F, ? extends T> function;
267 
TransformedCollection(Collection<F> fromCollection, Function<? super F, ? extends T> function)268     TransformedCollection(Collection<F> fromCollection, Function<? super F, ? extends T> function) {
269       this.fromCollection = checkNotNull(fromCollection);
270       this.function = checkNotNull(function);
271     }
272 
273     @Override
clear()274     public void clear() {
275       fromCollection.clear();
276     }
277 
278     @Override
isEmpty()279     public boolean isEmpty() {
280       return fromCollection.isEmpty();
281     }
282 
283     @Override
iterator()284     public Iterator<T> iterator() {
285       return Iterators.transform(fromCollection.iterator(), function);
286     }
287 
288     @Override
size()289     public int size() {
290       return fromCollection.size();
291     }
292   }
293 
294   /**
295    * Returns {@code true} if the collection {@code self} contains all of the elements in the
296    * collection {@code c}.
297    *
298    * <p>This method iterates over the specified collection {@code c}, checking each element returned
299    * by the iterator in turn to see if it is contained in the specified collection {@code self}. If
300    * all elements are so contained, {@code true} is returned, otherwise {@code false}.
301    *
302    * @param self a collection which might contain all elements in {@code c}
303    * @param c a collection whose elements might be contained by {@code self}
304    */
containsAllImpl(Collection<?> self, Collection<?> c)305   static boolean containsAllImpl(Collection<?> self, Collection<?> c) {
306     for (Object o : c) {
307       if (!self.contains(o)) {
308         return false;
309       }
310     }
311     return true;
312   }
313 
314   /** An implementation of {@link Collection#toString()}. */
toStringImpl(final Collection<?> collection)315   static String toStringImpl(final Collection<?> collection) {
316     StringBuilder sb = newStringBuilderForCollection(collection.size()).append('[');
317     boolean first = true;
318     for (Object o : collection) {
319       if (!first) {
320         sb.append(", ");
321       }
322       first = false;
323       if (o == collection) {
324         sb.append("(this Collection)");
325       } else {
326         sb.append(o);
327       }
328     }
329     return sb.append(']').toString();
330   }
331 
332   /** Returns best-effort-sized StringBuilder based on the given collection size. */
newStringBuilderForCollection(int size)333   static StringBuilder newStringBuilderForCollection(int size) {
334     checkNonnegative(size, "size");
335     return new StringBuilder((int) Math.min(size * 8L, Ints.MAX_POWER_OF_TWO));
336   }
337 
338   /**
339    * Returns a {@link Collection} of all the permutations of the specified {@link Iterable}.
340    *
341    * <p><i>Notes:</i> This is an implementation of the algorithm for Lexicographical Permutations
342    * Generation, described in Knuth's "The Art of Computer Programming", Volume 4, Chapter 7,
343    * Section 7.2.1.2. The iteration order follows the lexicographical order. This means that the
344    * first permutation will be in ascending order, and the last will be in descending order.
345    *
346    * <p>Duplicate elements are considered equal. For example, the list [1, 1] will have only one
347    * permutation, instead of two. This is why the elements have to implement {@link Comparable}.
348    *
349    * <p>An empty iterable has only one permutation, which is an empty list.
350    *
351    * <p>This method is equivalent to {@code Collections2.orderedPermutations(list,
352    * Ordering.natural())}.
353    *
354    * @param elements the original iterable whose elements have to be permuted.
355    * @return an immutable {@link Collection} containing all the different permutations of the
356    *     original iterable.
357    * @throws NullPointerException if the specified iterable is null or has any null elements.
358    * @since 12.0
359    */
360   @Beta
orderedPermutations( Iterable<E> elements)361   public static <E extends Comparable<? super E>> Collection<List<E>> orderedPermutations(
362       Iterable<E> elements) {
363     return orderedPermutations(elements, Ordering.natural());
364   }
365 
366   /**
367    * Returns a {@link Collection} of all the permutations of the specified {@link Iterable} using
368    * the specified {@link Comparator} for establishing the lexicographical ordering.
369    *
370    * <p>Examples:
371    *
372    * <pre>{@code
373    * for (List<String> perm : orderedPermutations(asList("b", "c", "a"))) {
374    *   println(perm);
375    * }
376    * // -> ["a", "b", "c"]
377    * // -> ["a", "c", "b"]
378    * // -> ["b", "a", "c"]
379    * // -> ["b", "c", "a"]
380    * // -> ["c", "a", "b"]
381    * // -> ["c", "b", "a"]
382    *
383    * for (List<Integer> perm : orderedPermutations(asList(1, 2, 2, 1))) {
384    *   println(perm);
385    * }
386    * // -> [1, 1, 2, 2]
387    * // -> [1, 2, 1, 2]
388    * // -> [1, 2, 2, 1]
389    * // -> [2, 1, 1, 2]
390    * // -> [2, 1, 2, 1]
391    * // -> [2, 2, 1, 1]
392    * }</pre>
393    *
394    * <p><i>Notes:</i> This is an implementation of the algorithm for Lexicographical Permutations
395    * Generation, described in Knuth's "The Art of Computer Programming", Volume 4, Chapter 7,
396    * Section 7.2.1.2. The iteration order follows the lexicographical order. This means that the
397    * first permutation will be in ascending order, and the last will be in descending order.
398    *
399    * <p>Elements that compare equal are considered equal and no new permutations are created by
400    * swapping them.
401    *
402    * <p>An empty iterable has only one permutation, which is an empty list.
403    *
404    * @param elements the original iterable whose elements have to be permuted.
405    * @param comparator a comparator for the iterable's elements.
406    * @return an immutable {@link Collection} containing all the different permutations of the
407    *     original iterable.
408    * @throws NullPointerException If the specified iterable is null, has any null elements, or if
409    *     the specified comparator is null.
410    * @since 12.0
411    */
412   @Beta
orderedPermutations( Iterable<E> elements, Comparator<? super E> comparator)413   public static <E> Collection<List<E>> orderedPermutations(
414       Iterable<E> elements, Comparator<? super E> comparator) {
415     return new OrderedPermutationCollection<E>(elements, comparator);
416   }
417 
418   private static final class OrderedPermutationCollection<E> extends AbstractCollection<List<E>> {
419     final ImmutableList<E> inputList;
420     final Comparator<? super E> comparator;
421     final int size;
422 
OrderedPermutationCollection(Iterable<E> input, Comparator<? super E> comparator)423     OrderedPermutationCollection(Iterable<E> input, Comparator<? super E> comparator) {
424       this.inputList = ImmutableList.sortedCopyOf(comparator, input);
425       this.comparator = comparator;
426       this.size = calculateSize(inputList, comparator);
427     }
428 
429     /**
430      * The number of permutations with repeated elements is calculated as follows:
431      *
432      * <ul>
433      *   <li>For an empty list, it is 1 (base case).
434      *   <li>When r numbers are added to a list of n-r elements, the number of permutations is
435      *       increased by a factor of (n choose r).
436      * </ul>
437      */
calculateSize( List<E> sortedInputList, Comparator<? super E> comparator)438     private static <E> int calculateSize(
439         List<E> sortedInputList, Comparator<? super E> comparator) {
440       int permutations = 1;
441       int n = 1;
442       int r = 1;
443       while (n < sortedInputList.size()) {
444         int comparison = comparator.compare(sortedInputList.get(n - 1), sortedInputList.get(n));
445         if (comparison < 0) {
446           // We move to the next non-repeated element.
447           permutations = IntMath.saturatedMultiply(permutations, IntMath.binomial(n, r));
448           r = 0;
449           if (permutations == Integer.MAX_VALUE) {
450             return Integer.MAX_VALUE;
451           }
452         }
453         n++;
454         r++;
455       }
456       return IntMath.saturatedMultiply(permutations, IntMath.binomial(n, r));
457     }
458 
459     @Override
size()460     public int size() {
461       return size;
462     }
463 
464     @Override
isEmpty()465     public boolean isEmpty() {
466       return false;
467     }
468 
469     @Override
iterator()470     public Iterator<List<E>> iterator() {
471       return new OrderedPermutationIterator<E>(inputList, comparator);
472     }
473 
474     @Override
contains(@heckForNull Object obj)475     public boolean contains(@CheckForNull Object obj) {
476       if (obj instanceof List) {
477         List<?> list = (List<?>) obj;
478         return isPermutation(inputList, list);
479       }
480       return false;
481     }
482 
483     @Override
toString()484     public String toString() {
485       return "orderedPermutationCollection(" + inputList + ")";
486     }
487   }
488 
489   private static final class OrderedPermutationIterator<E> extends AbstractIterator<List<E>> {
490     @CheckForNull List<E> nextPermutation;
491     final Comparator<? super E> comparator;
492 
OrderedPermutationIterator(List<E> list, Comparator<? super E> comparator)493     OrderedPermutationIterator(List<E> list, Comparator<? super E> comparator) {
494       this.nextPermutation = Lists.newArrayList(list);
495       this.comparator = comparator;
496     }
497 
498     @Override
499     @CheckForNull
computeNext()500     protected List<E> computeNext() {
501       if (nextPermutation == null) {
502         return endOfData();
503       }
504       ImmutableList<E> next = ImmutableList.copyOf(nextPermutation);
505       calculateNextPermutation();
506       return next;
507     }
508 
calculateNextPermutation()509     void calculateNextPermutation() {
510       int j = findNextJ();
511       if (j == -1) {
512         nextPermutation = null;
513         return;
514       }
515       /*
516        * requireNonNull is safe because we don't clear nextPermutation until we're done calling this
517        * method.
518        */
519       requireNonNull(nextPermutation);
520 
521       int l = findNextL(j);
522       Collections.swap(nextPermutation, j, l);
523       int n = nextPermutation.size();
524       Collections.reverse(nextPermutation.subList(j + 1, n));
525     }
526 
findNextJ()527     int findNextJ() {
528       /*
529        * requireNonNull is safe because we don't clear nextPermutation until we're done calling this
530        * method.
531        */
532       requireNonNull(nextPermutation);
533       for (int k = nextPermutation.size() - 2; k >= 0; k--) {
534         if (comparator.compare(nextPermutation.get(k), nextPermutation.get(k + 1)) < 0) {
535           return k;
536         }
537       }
538       return -1;
539     }
540 
findNextL(int j)541     int findNextL(int j) {
542       /*
543        * requireNonNull is safe because we don't clear nextPermutation until we're done calling this
544        * method.
545        */
546       requireNonNull(nextPermutation);
547       E ak = nextPermutation.get(j);
548       for (int l = nextPermutation.size() - 1; l > j; l--) {
549         if (comparator.compare(ak, nextPermutation.get(l)) < 0) {
550           return l;
551         }
552       }
553       throw new AssertionError("this statement should be unreachable");
554     }
555   }
556 
557   /**
558    * Returns a {@link Collection} of all the permutations of the specified {@link Collection}.
559    *
560    * <p><i>Notes:</i> This is an implementation of the Plain Changes algorithm for permutations
561    * generation, described in Knuth's "The Art of Computer Programming", Volume 4, Chapter 7,
562    * Section 7.2.1.2.
563    *
564    * <p>If the input list contains equal elements, some of the generated permutations will be equal.
565    *
566    * <p>An empty collection has only one permutation, which is an empty list.
567    *
568    * @param elements the original collection whose elements have to be permuted.
569    * @return an immutable {@link Collection} containing all the different permutations of the
570    *     original collection.
571    * @throws NullPointerException if the specified collection is null or has any null elements.
572    * @since 12.0
573    */
574   @Beta
permutations(Collection<E> elements)575   public static <E> Collection<List<E>> permutations(Collection<E> elements) {
576     return new PermutationCollection<E>(ImmutableList.copyOf(elements));
577   }
578 
579   private static final class PermutationCollection<E> extends AbstractCollection<List<E>> {
580     final ImmutableList<E> inputList;
581 
PermutationCollection(ImmutableList<E> input)582     PermutationCollection(ImmutableList<E> input) {
583       this.inputList = input;
584     }
585 
586     @Override
size()587     public int size() {
588       return IntMath.factorial(inputList.size());
589     }
590 
591     @Override
isEmpty()592     public boolean isEmpty() {
593       return false;
594     }
595 
596     @Override
iterator()597     public Iterator<List<E>> iterator() {
598       return new PermutationIterator<E>(inputList);
599     }
600 
601     @Override
contains(@heckForNull Object obj)602     public boolean contains(@CheckForNull Object obj) {
603       if (obj instanceof List) {
604         List<?> list = (List<?>) obj;
605         return isPermutation(inputList, list);
606       }
607       return false;
608     }
609 
610     @Override
toString()611     public String toString() {
612       return "permutations(" + inputList + ")";
613     }
614   }
615 
616   private static class PermutationIterator<E> extends AbstractIterator<List<E>> {
617     final List<E> list;
618     final int[] c;
619     final int[] o;
620     int j;
621 
PermutationIterator(List<E> list)622     PermutationIterator(List<E> list) {
623       this.list = new ArrayList<E>(list);
624       int n = list.size();
625       c = new int[n];
626       o = new int[n];
627       Arrays.fill(c, 0);
628       Arrays.fill(o, 1);
629       j = Integer.MAX_VALUE;
630     }
631 
632     @Override
633     @CheckForNull
computeNext()634     protected List<E> computeNext() {
635       if (j <= 0) {
636         return endOfData();
637       }
638       ImmutableList<E> next = ImmutableList.copyOf(list);
639       calculateNextPermutation();
640       return next;
641     }
642 
calculateNextPermutation()643     void calculateNextPermutation() {
644       j = list.size() - 1;
645       int s = 0;
646 
647       // Handle the special case of an empty list. Skip the calculation of the
648       // next permutation.
649       if (j == -1) {
650         return;
651       }
652 
653       while (true) {
654         int q = c[j] + o[j];
655         if (q < 0) {
656           switchDirection();
657           continue;
658         }
659         if (q == j + 1) {
660           if (j == 0) {
661             break;
662           }
663           s++;
664           switchDirection();
665           continue;
666         }
667 
668         Collections.swap(list, j - c[j] + s, j - q + s);
669         c[j] = q;
670         break;
671       }
672     }
673 
switchDirection()674     void switchDirection() {
675       o[j] = -o[j];
676       j--;
677     }
678   }
679 
680   /** Returns {@code true} if the second list is a permutation of the first. */
isPermutation(List<?> first, List<?> second)681   private static boolean isPermutation(List<?> first, List<?> second) {
682     if (first.size() != second.size()) {
683       return false;
684     }
685     ObjectCountHashMap<?> firstCounts = counts(first);
686     ObjectCountHashMap<?> secondCounts = counts(second);
687     if (first.size() != second.size()) {
688       return false;
689     }
690     for (int i = 0; i < first.size(); i++) {
691       if (firstCounts.getValue(i) != secondCounts.get(firstCounts.getKey(i))) {
692         return false;
693       }
694     }
695     return true;
696   }
697 
counts( Collection<E> collection)698   private static <E extends @Nullable Object> ObjectCountHashMap<E> counts(
699       Collection<E> collection) {
700     ObjectCountHashMap<E> map = new ObjectCountHashMap<>();
701     for (E e : collection) {
702       map.put(e, map.get(e) + 1);
703     }
704     return map;
705   }
706 }
707