CollectionUtils.java revision 7d5439950fe52a7be4fa6cb222e301f78604f96f
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
32package org.jf.util;
33
34import com.google.common.base.Predicate;
35import com.google.common.collect.ImmutableSortedSet;
36import com.google.common.collect.Ordering;
37import com.google.common.primitives.Ints;
38
39import javax.annotation.Nonnull;
40import java.util.*;
41
42public class CollectionUtils {
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
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
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
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
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
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
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