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