1 /*
2  * Copyright (C) 2010 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package libcore.util;
18 
19 import java.lang.ref.Reference;
20 import java.util.ArrayList;
21 import java.util.Collections;
22 import java.util.Comparator;
23 import java.util.Iterator;
24 import java.util.List;
25 
26 public final class CollectionUtils {
CollectionUtils()27     private CollectionUtils() {}
28 
29     /**
30      * Returns an iterator over the values referenced by the elements of {@code
31      * iterable}.
32      *
33      * @param trim true to remove reference objects from the iterable after
34      *     their referenced values have been cleared.
35      */
dereferenceIterable( final Iterable<? extends Reference<T>> iterable, final boolean trim)36     public static <T> Iterable<T> dereferenceIterable(
37             final Iterable<? extends Reference<T>> iterable, final boolean trim) {
38         return new Iterable<T>() {
39             public Iterator<T> iterator() {
40                 return new Iterator<T>() {
41                     private final Iterator<? extends Reference<T>> delegate = iterable.iterator();
42                     private boolean removeIsOkay;
43                     private T next;
44 
45                     private void computeNext() {
46                         removeIsOkay = false;
47                         while (next == null && delegate.hasNext()) {
48                             next = delegate.next().get();
49                             if (trim && next == null) {
50                                 delegate.remove();
51                             }
52                         }
53                     }
54 
55                     @Override public boolean hasNext() {
56                         computeNext();
57                         return next != null;
58                     }
59 
60                     @Override public T next() {
61                         if (!hasNext()) {
62                             throw new IllegalStateException();
63                         }
64                         T result = next;
65                         removeIsOkay = true;
66                         next = null;
67                         return result;
68                     }
69 
70                     public void remove() {
71                         if (!removeIsOkay) {
72                             throw new IllegalStateException();
73                         }
74                         delegate.remove();
75                     }
76                 };
77             }
78         };
79     }
80 
81     /**
82      * Sorts and removes duplicate elements from {@code list}. This method does
83      * not use {@link Object#equals}: only the comparator defines equality.
84      */
85     public static <T> void removeDuplicates(List<T> list, Comparator<? super T> comparator) {
86         Collections.sort(list, comparator);
87         int j = 1;
88         for (int i = 1; i < list.size(); i++) {
89             if (comparator.compare(list.get(j - 1), list.get(i)) != 0) {
90                 T object = list.get(i);
91                 list.set(j++, object);
92             }
93         }
94         if (j < list.size()) {
95             list.subList(j, list.size()).clear();
96         }
97     }
98 }
99