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