001 /*--------------------------------------------------------------------------+ 002 $Id: CollectionUtils.java 27324 2010-03-31 08:53:26Z hummelb $ 003 | | 004 | Copyright 2005-2010 Technische Universitaet Muenchen | 005 | | 006 | Licensed under the Apache License, Version 2.0 (the "License"); | 007 | you may not use this file except in compliance with the License. | 008 | You may obtain a copy of the License at | 009 | | 010 | http://www.apache.org/licenses/LICENSE-2.0 | 011 | | 012 | Unless required by applicable law or agreed to in writing, software | 013 | distributed under the License is distributed on an "AS IS" BASIS, | 014 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 015 | See the License for the specific language governing permissions and | 016 | limitations under the License. | 017 +--------------------------------------------------------------------------*/ 018 package edu.tum.cs.commons.collections; 019 020 import java.util.ArrayList; 021 import java.util.Arrays; 022 import java.util.Collection; 023 import java.util.Collections; 024 import java.util.Comparator; 025 import java.util.Deque; 026 import java.util.HashSet; 027 import java.util.Iterator; 028 import java.util.List; 029 import java.util.Map; 030 import java.util.Set; 031 import java.util.SortedMap; 032 import java.util.SortedSet; 033 034 /** 035 * This class offers utility methods for collections. In can be seen as an 036 * extension to {@link Collections}. 037 * 038 * @author Florian Deissenboeck 039 * @author $Author: hummelb $ 040 * 041 * @version $Revision: 27324 $ 042 * @levd.rating GREEN Hash: 18A8495D2E7BB7DE351987B60C0E3338 043 */ 044 public class CollectionUtils { 045 /** Empty unmodifiable list. */ 046 @SuppressWarnings("unchecked") 047 private static final UnmodifiableList<?> EMPTY_LIST = new UnmodifiableList<Object>( 048 Collections.EMPTY_LIST); 049 050 /** Empty unmodifiable map. */ 051 @SuppressWarnings("unchecked") 052 private static final UnmodifiableMap<?, ?> EMPTY_MAP = new UnmodifiableMap<Object, Object>( 053 Collections.EMPTY_MAP); 054 055 /** Empty unmodifiable set. */ 056 @SuppressWarnings("unchecked") 057 private static final UnmodifiableSet<?> EMPTY_SET = new UnmodifiableSet<Object>( 058 Collections.EMPTY_SET); 059 060 /** 061 * Create an hashed set from an array. 062 * 063 * @param <T> 064 * type 065 * @param elements 066 * elements in the set. 067 * @return the set. 068 * @see Arrays#asList(Object[]) 069 */ 070 public static <T> HashSet<T> asHashSet(T... elements) { 071 HashSet<T> result = new HashSet<T>(); 072 073 Collections.addAll(result, elements); 074 075 return result; 076 } 077 078 /** 079 * Returns a new unmodifiable collection wrapping the given collection. This 080 * method is here to avoid retyping the generic argument for the collection 081 * class. 082 */ 083 public static <T> UnmodifiableCollection<T> asUnmodifiable(Collection<T> c) { 084 return new UnmodifiableCollection<T>(c); 085 } 086 087 /** 088 * Returns a new unmodifiable hashed list map wrapping the given map. This 089 * method is here to avoid retyping the generic arguments for the sorted map 090 * class. 091 */ 092 public static <S, T> UnmodifiableHashedListMap<S, T> asUnmodifiable( 093 HashedListMap<S, T> m) { 094 return new UnmodifiableHashedListMap<S, T>(m); 095 } 096 097 /** 098 * Returns a new unmodifiable list wrapping the given list. This method is 099 * here to avoid retyping the generic argument for the list class. 100 */ 101 public static <T> UnmodifiableList<T> asUnmodifiable(List<T> l) { 102 return new UnmodifiableList<T>(l); 103 } 104 105 /** 106 * Returns a new unmodifiable map wrapping the given map. This method is 107 * here to avoid retyping the generic arguments for the map class. 108 */ 109 public static <S, T> UnmodifiableMap<S, T> asUnmodifiable(Map<S, T> m) { 110 return new UnmodifiableMap<S, T>(m); 111 } 112 113 /** 114 * Returns a new unmodifiable set wrapping the given set. This method is 115 * here to avoid retyping the generic argument for the set class. 116 */ 117 public static <T> UnmodifiableSet<T> asUnmodifiable(Set<T> s) { 118 return new UnmodifiableSet<T>(s); 119 } 120 121 /** 122 * Returns a new unmodifiable sorted map wrapping the given sorted map. This 123 * method is here to avoid retyping the generic arguments for the sorted map 124 * class. 125 */ 126 public static <S, T> UnmodifiableSortedMap<S, T> asUnmodifiable( 127 SortedMap<S, T> m) { 128 return new UnmodifiableSortedMap<S, T>(m); 129 } 130 131 /** 132 * Returns a new unmodifiable sorted set wrapping the given sorted set. This 133 * method is here to avoid retyping the generic argument for the sorted set 134 * class. 135 */ 136 public static <T> UnmodifiableSortedSet<T> asUnmodifiable(SortedSet<T> s) { 137 return new UnmodifiableSortedSet<T>(s); 138 } 139 140 /** 141 * The way this method is defined allows to assign it to all parameterized 142 * types, i.e. bot of the following statements are accepted by the compiler 143 * without warnings: 144 * 145 * <pre> 146 * UnmodifiableList<String> emptyList = CollectionUtils.emptyList(); 147 * 148 * UnmodifiableList<Date> emptyList = CollectionUtils.emptyList(); 149 * </pre> 150 * 151 * @param <T> 152 * @return the emtpy list 153 */ 154 @SuppressWarnings("unchecked") 155 public static final <T> UnmodifiableList<T> emptyList() { 156 return (UnmodifiableList<T>) EMPTY_LIST; 157 } 158 159 /** Returns an empty map. See {@link #emptyList()} for further details. */ 160 @SuppressWarnings("unchecked") 161 public static final <S, T> UnmodifiableMap<S, T> emptyMap() { 162 return (UnmodifiableMap<S, T>) EMPTY_MAP; 163 } 164 165 /** Returns an empty set. See {@link #emptyList()} for further details. */ 166 @SuppressWarnings("unchecked") 167 public static final <T> UnmodifiableSet<T> emptySet() { 168 return (UnmodifiableSet<T>) EMPTY_SET; 169 } 170 171 /** 172 * Sorts the specified list into ascending order, according to the 173 * <i>natural ordering</i> of its elements. 174 * <p> 175 * All elements in the list must implement the Comparable interface. 176 * Furthermore, all elements in the list must be mutually comparable (that 177 * is, e1.compareTo(e2) must not throw a <code>ClassCastException</code> for 178 * any elements e1 and e2 in the list). 179 * <p> 180 * This method does not modify the original collection. 181 */ 182 public static <T extends Comparable<? super T>> List<T> sort( 183 Collection<T> collection) { 184 ArrayList<T> list = new ArrayList<T>(collection); 185 Collections.sort(list); 186 return list; 187 } 188 189 /** 190 * Returns a list that contains the elements of the specified list in 191 * reversed order. 192 * <p> 193 * This method does not modify the original collection. 194 */ 195 public static <T> List<T> reverse(Collection<T> list) { 196 ArrayList<T> reversed = new ArrayList<T>(list); 197 Collections.reverse(reversed); 198 return reversed; 199 } 200 201 /** 202 * Sorts the specified list according to the order induced by the specified 203 * comparator. 204 * <p> 205 * All elements in the list must implement the Comparable interface. 206 * Furthermore, all elements in the list must be mutually comparable (that 207 * is, e1.compareTo(e2) must not throw a <code>ClassCastException</code> for 208 * any elements e1 and e2 in the list). 209 * <p> 210 * This method does not modify the original collection. 211 */ 212 public static <T> List<T> sort(Collection<T> collection, 213 Comparator<? super T> comparator) { 214 ArrayList<T> list = new ArrayList<T>(collection); 215 Collections.sort(list, comparator); 216 return list; 217 } 218 219 /** Returns a sorted unmodifiable list for a collection. */ 220 public static <T extends Comparable<T>> UnmodifiableList<T> asSortedUnmodifiableList( 221 Collection<T> collection) { 222 return asUnmodifiable(sort(collection)); 223 } 224 225 /** 226 * Returns a sorted unmodifiable list for a collection. 227 * 228 * @param comparator 229 * Comparator used for sorting 230 */ 231 public static <T extends Comparable<T>> UnmodifiableList<T> asSortedUnmodifiableList( 232 Collection<T> collection, Comparator<? super T> comparator) { 233 return asUnmodifiable(sort(collection, comparator)); 234 } 235 236 /** 237 * Returns one object from an {@link Iterable} or <code>null</code> if the 238 * iterable is empty. 239 */ 240 public static <T> T getAny(Iterable<T> iterable) { 241 Iterator<T> iterator = iterable.iterator(); 242 if (!iterator.hasNext()) { 243 return null; 244 } 245 return iterator.next(); 246 } 247 248 /** 249 * Convert collection to array. This is a bit cleaner version of 250 * {@link Collection#toArray(Object[])}. 251 */ 252 @SuppressWarnings("unchecked") 253 public static <T> T[] toArray(Collection<? extends T> collection, 254 Class<T> type) { 255 T[] result = (T[]) java.lang.reflect.Array.newInstance(type, collection 256 .size()); 257 258 Iterator<? extends T> it = collection.iterator(); 259 for (int i = 0; i < collection.size(); i++) { 260 result[i] = it.next(); 261 } 262 263 return result; 264 } 265 266 /** 267 * Copy an array. This is a shortcut for 268 * {@link Arrays#copyOf(Object[], int)} that does not require to specify the 269 * length. 270 */ 271 public static <T> T[] copyArray(T[] original) { 272 return Arrays.copyOf(original, original.length); 273 } 274 275 /** 276 * Compute list of unordered pairs for all elements contained in a 277 * collection. 278 */ 279 public static <T> List<ImmutablePair<T, T>> computeUnorderedPairs( 280 Collection<T> collection) { 281 List<T> elements = new ArrayList<T>(collection); 282 List<ImmutablePair<T, T>> pairs = new ArrayList<ImmutablePair<T, T>>(); 283 284 int size = elements.size(); 285 for (int firstIndex = 0; firstIndex < size; firstIndex++) { 286 for (int secondIndex = firstIndex + 1; secondIndex < size; secondIndex++) { 287 pairs.add(new ImmutablePair<T, T>(elements.get(firstIndex), 288 elements.get(secondIndex))); 289 } 290 } 291 292 return pairs; 293 } 294 295 /** Returns the last element in list or <code>null</code>, if list is empty. */ 296 @SuppressWarnings("unchecked") 297 public static <T> T getLast(List<T> list) { 298 if (list.isEmpty()) { 299 return null; 300 } 301 if (list instanceof Deque<?>) { 302 return ((Deque<T>) list).getLast(); 303 } 304 return list.get(list.size() - 1); 305 } 306 307 }