CollectionUtils.java revision 4ffbfa2e71ffdf6ecaa8429b19ce29daa28e9fc4
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            int res = comparator.compare(element1, elements2.next());
81            if (res != 0) return res;
82        }
83        return 0;
84    }
85
86    public static <T extends Comparable<? super T>> int compareAsIterable(@Nonnull Iterable<? extends T> it1,
87                                                                          @Nonnull Iterable<? extends T> it2) {
88        Iterator<? extends T> elements2 = it2.iterator();
89        for (T element1: it1) {
90            int res = element1.compareTo(elements2.next());
91            if (res != 0) return res;
92        }
93        return 0;
94    }
95
96    public static <T> int compareAsList(@Nonnull Comparator<? super T> elementComparator,
97                                        @Nonnull Collection<? extends T> list1,
98                                        @Nonnull Collection<? extends T> list2) {
99        int res = Ints.compare(list1.size(), list2.size());
100        if (res != 0) return res;
101        Iterator<? extends T> elements2 = list2.iterator();
102        for (T element1: list1) {
103            res = elementComparator.compare(element1, elements2.next());
104            if (res != 0) return res;
105        }
106        return 0;
107    }
108
109    @Nonnull
110    public static <T> Comparator<Collection<? extends T>> listComparator(
111            @Nonnull final Comparator<? super T> elementComparator) {
112        return new Comparator<Collection<? extends T>>() {
113            @Override
114            public int compare(Collection<? extends T> list1, Collection<? extends T> list2) {
115                return compareAsList(elementComparator, list1, list2);
116            }
117        };
118    }
119
120    public static <T> boolean isNaturalSortedSet(@Nonnull Iterable<? extends T> it) {
121        if (it instanceof SortedSet) {
122            SortedSet<? extends T> sortedSet = (SortedSet<? extends T>)it;
123            Comparator<?> comparator = sortedSet.comparator();
124            return (comparator == null) || comparator.equals(Ordering.natural());
125        }
126        return false;
127    }
128
129    public static <T> boolean isSortedSet(@Nonnull Comparator<? extends T> elementComparator,
130                                          @Nonnull Iterable<? extends T> it) {
131        if (it instanceof SortedSet) {
132            SortedSet<? extends T> sortedSet = (SortedSet<? extends T>)it;
133            Comparator<?> comparator = sortedSet.comparator();
134            if (comparator == null) {
135                return elementComparator.equals(Ordering.natural());
136            }
137            return elementComparator.equals(comparator);
138        }
139        return false;
140    }
141
142    @Nonnull
143    private static <T> SortedSet<? extends T> toNaturalSortedSet(@Nonnull Collection<? extends T> collection) {
144        if (isNaturalSortedSet(collection)) {
145            return (SortedSet<? extends T>)collection;
146        }
147        return ImmutableSortedSet.copyOf(collection);
148    }
149
150    @Nonnull
151    private static <T> SortedSet<? extends T> toSortedSet(@Nonnull Comparator<? super T> elementComparator,
152                                                          @Nonnull Collection<? extends T> collection) {
153        if (collection instanceof SortedSet) {
154            SortedSet<? extends T> sortedSet = (SortedSet<? extends T>)collection;
155            Comparator<?> comparator = sortedSet.comparator();
156            if (comparator != null && comparator.equals(elementComparator)) {
157                return sortedSet;
158            }
159        }
160        return ImmutableSortedSet.copyOf(elementComparator, collection);
161    }
162
163    @Nonnull
164    public static <T> Comparator<Collection<? extends T>> setComparator(
165            @Nonnull final Comparator<? super T> elementComparator) {
166        return new Comparator<Collection<? extends T>>() {
167            @Override
168            public int compare(Collection<? extends T> list1, Collection<? extends T> list2) {
169                return compareAsSet(elementComparator, list1, list2);
170            }
171        };
172    }
173
174    public static <T extends Comparable<T>> int compareAsSet(@Nonnull Collection<? extends T> set1,
175                                                             @Nonnull Collection<? extends T> set2) {
176        int res = Ints.compare(set1.size(), set2.size());
177        if (res != 0) return res;
178
179        SortedSet<? extends T> sortedSet1 = toNaturalSortedSet(set1);
180        SortedSet<? extends T> sortedSet2 = toNaturalSortedSet(set2);
181
182        Iterator<? extends T> elements2 = set2.iterator();
183        for (T element1: set1) {
184            res = element1.compareTo(elements2.next());
185            if (res != 0) return res;
186        }
187        return 0;
188    }
189
190    public static <T> int compareAsSet(@Nonnull Comparator<? super T> elementComparator,
191                                       @Nonnull Collection<? extends T> list1,
192                                       @Nonnull Collection<? extends T> list2) {
193        int res = Ints.compare(list1.size(), list2.size());
194        if (res != 0) return res;
195
196        SortedSet<? extends T> set1 = toSortedSet(elementComparator, list1);
197        SortedSet<? extends T> set2 = toSortedSet(elementComparator, list2);
198
199        Iterator<? extends T> elements2 = set2.iterator();
200        for (T element1: set1) {
201            res = elementComparator.compare(element1, elements2.next());
202            if (res != 0) return res;
203        }
204        return 0;
205    }
206}
207