1 /*
2  * Copyright 2012, Google Inc.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are
7  * met:
8  *
9  *     * Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  *     * Redistributions in binary form must reproduce the above
12  * copyright notice, this list of conditions and the following disclaimer
13  * in the documentation and/or other materials provided with the
14  * distribution.
15  *     * Neither the name of Google Inc. nor the names of its
16  * contributors may be used to endorse or promote products derived from
17  * this software without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  */
31 
32 package org.jf.util;
33 
34 import com.google.common.base.Predicate;
35 import com.google.common.collect.ImmutableSortedSet;
36 import com.google.common.collect.Ordering;
37 import com.google.common.primitives.Ints;
38 
39 import javax.annotation.Nonnull;
40 import java.util.*;
41 
42 public class CollectionUtils {
listHashCode(@onnull Iterable<T> iterable)43     public static <T> int listHashCode(@Nonnull Iterable<T> iterable) {
44         int hashCode = 1;
45         for (T item: iterable) {
46             hashCode = hashCode*31 + item.hashCode();
47         }
48         return hashCode;
49     }
50 
lastIndexOf(@onnull Iterable<T> iterable, @Nonnull Predicate<? super T> predicate)51     public static <T> int lastIndexOf(@Nonnull Iterable<T> iterable, @Nonnull Predicate<? super T> predicate) {
52         int index = 0;
53         int lastMatchingIndex = -1;
54         for (T item: iterable) {
55             if (predicate.apply(item)) {
56                 lastMatchingIndex = index;
57             }
58             index++;
59         }
60         return lastMatchingIndex;
61     }
62 
compareAsList(@onnull Collection<? extends T> list1, @Nonnull Collection<? extends T> list2)63     public static <T extends Comparable<? super T>> int compareAsList(@Nonnull Collection<? extends T> list1,
64                                                                       @Nonnull Collection<? extends T> list2) {
65         int res = Ints.compare(list1.size(), list2.size());
66         if (res != 0) return res;
67         Iterator<? extends T> elements2 = list2.iterator();
68         for (T element1: list1) {
69             res = element1.compareTo(elements2.next());
70             if (res != 0) return res;
71         }
72         return 0;
73     }
74 
compareAsIterable(@onnull Comparator<? super T> comparator, @Nonnull Iterable<? extends T> it1, @Nonnull Iterable<? extends T> it2)75     public static <T> int compareAsIterable(@Nonnull Comparator<? super T> comparator,
76                                             @Nonnull Iterable<? extends T> it1,
77                                             @Nonnull Iterable<? extends T> it2) {
78         Iterator<? extends T> elements2 = it2.iterator();
79         for (T element1: it1) {
80             T element2;
81             try {
82                 element2 = elements2.next();
83             } catch (NoSuchElementException ex) {
84                 return 1;
85             }
86             int res = comparator.compare(element1, element2);
87             if (res != 0) return res;
88         }
89         if (elements2.hasNext()) {
90             return -1;
91         }
92         return 0;
93     }
94 
compareAsIterable(@onnull Iterable<? extends T> it1, @Nonnull Iterable<? extends T> it2)95     public static <T extends Comparable<? super T>> int compareAsIterable(@Nonnull Iterable<? extends T> it1,
96                                                                           @Nonnull Iterable<? extends T> it2) {
97         Iterator<? extends T> elements2 = it2.iterator();
98         for (T element1: it1) {
99             T element2;
100             try {
101                 element2 = elements2.next();
102             } catch (NoSuchElementException ex) {
103                 return 1;
104             }
105             int res = element1.compareTo(element2);
106             if (res != 0) return res;
107         }
108         if (elements2.hasNext()) {
109             return -1;
110         }
111         return 0;
112     }
113 
compareAsList(@onnull Comparator<? super T> elementComparator, @Nonnull Collection<? extends T> list1, @Nonnull Collection<? extends T> list2)114     public static <T> int compareAsList(@Nonnull Comparator<? super T> elementComparator,
115                                         @Nonnull Collection<? extends T> list1,
116                                         @Nonnull Collection<? extends T> list2) {
117         int res = Ints.compare(list1.size(), list2.size());
118         if (res != 0) return res;
119         Iterator<? extends T> elements2 = list2.iterator();
120         for (T element1: list1) {
121             res = elementComparator.compare(element1, elements2.next());
122             if (res != 0) return res;
123         }
124         return 0;
125     }
126 
127     @Nonnull
listComparator( @onnull final Comparator<? super T> elementComparator)128     public static <T> Comparator<Collection<? extends T>> listComparator(
129             @Nonnull final Comparator<? super T> elementComparator) {
130         return new Comparator<Collection<? extends T>>() {
131             @Override
132             public int compare(Collection<? extends T> list1, Collection<? extends T> list2) {
133                 return compareAsList(elementComparator, list1, list2);
134             }
135         };
136     }
137 
138     public static <T> boolean isNaturalSortedSet(@Nonnull Iterable<? extends T> it) {
139         if (it instanceof SortedSet) {
140             SortedSet<? extends T> sortedSet = (SortedSet<? extends T>)it;
141             Comparator<?> comparator = sortedSet.comparator();
142             return (comparator == null) || comparator.equals(Ordering.natural());
143         }
144         return false;
145     }
146 
147     public static <T> boolean isSortedSet(@Nonnull Comparator<? extends T> elementComparator,
148                                           @Nonnull Iterable<? extends T> it) {
149         if (it instanceof SortedSet) {
150             SortedSet<? extends T> sortedSet = (SortedSet<? extends T>)it;
151             Comparator<?> comparator = sortedSet.comparator();
152             if (comparator == null) {
153                 return elementComparator.equals(Ordering.natural());
154             }
155             return elementComparator.equals(comparator);
156         }
157         return false;
158     }
159 
160     @Nonnull
161     private static <T> SortedSet<? extends T> toNaturalSortedSet(@Nonnull Collection<? extends T> collection) {
162         if (isNaturalSortedSet(collection)) {
163             return (SortedSet<? extends T>)collection;
164         }
165         return ImmutableSortedSet.copyOf(collection);
166     }
167 
168     @Nonnull
169     private static <T> SortedSet<? extends T> toSortedSet(@Nonnull Comparator<? super T> elementComparator,
170                                                           @Nonnull Collection<? extends T> collection) {
171         if (collection instanceof SortedSet) {
172             SortedSet<? extends T> sortedSet = (SortedSet<? extends T>)collection;
173             Comparator<?> comparator = sortedSet.comparator();
174             if (comparator != null && comparator.equals(elementComparator)) {
175                 return sortedSet;
176             }
177         }
178         return ImmutableSortedSet.copyOf(elementComparator, collection);
179     }
180 
181     @Nonnull
182     public static <T> Comparator<Collection<? extends T>> setComparator(
183             @Nonnull final Comparator<? super T> elementComparator) {
184         return new Comparator<Collection<? extends T>>() {
185             @Override
186             public int compare(Collection<? extends T> list1, Collection<? extends T> list2) {
187                 return compareAsSet(elementComparator, list1, list2);
188             }
189         };
190     }
191 
192     public static <T extends Comparable<T>> int compareAsSet(@Nonnull Collection<? extends T> set1,
193                                                              @Nonnull Collection<? extends T> set2) {
194         int res = Ints.compare(set1.size(), set2.size());
195         if (res != 0) return res;
196 
197         SortedSet<? extends T> sortedSet1 = toNaturalSortedSet(set1);
198         SortedSet<? extends T> sortedSet2 = toNaturalSortedSet(set2);
199 
200         Iterator<? extends T> elements2 = set2.iterator();
201         for (T element1: set1) {
202             res = element1.compareTo(elements2.next());
203             if (res != 0) return res;
204         }
205         return 0;
206     }
207 
208     public static <T> int compareAsSet(@Nonnull Comparator<? super T> elementComparator,
209                                        @Nonnull Collection<? extends T> list1,
210                                        @Nonnull Collection<? extends T> list2) {
211         int res = Ints.compare(list1.size(), list2.size());
212         if (res != 0) return res;
213 
214         SortedSet<? extends T> set1 = toSortedSet(elementComparator, list1);
215         SortedSet<? extends T> set2 = toSortedSet(elementComparator, list2);
216 
217         Iterator<? extends T> elements2 = set2.iterator();
218         for (T element1: set1) {
219             res = elementComparator.compare(element1, elements2.next());
220             if (res != 0) return res;
221         }
222         return 0;
223     }
224 }
225