blob: 183945ca13825ac23271706a8d2948f66692b527 [file] [log] [blame]
Eugene Susla6a7006a2017-03-13 12:57:58 -07001/*
2 * Copyright (C) 2017 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
17package com.android.internal.util;
18
19import android.annotation.NonNull;
20import android.annotation.Nullable;
21
22import java.util.ArrayList;
23import java.util.Collection;
24import java.util.Collections;
25import java.util.List;
26import java.util.function.Function;
27import java.util.stream.Stream;
28
29/**
30 * Utility methods for dealing with (typically {@link Nullable}) {@link Collection}s
31 *
32 * Unless a method specifies otherwise, a null value for a collection is treated as an empty
33 * collection of that type.
34 */
35public class CollectionUtils {
36 private CollectionUtils() { /* cannot be instantiated */ }
37
38 /**
39 * Returns a list of items from the provided list that match the given condition.
40 *
41 * This is similar to {@link Stream#filter} but without the overhead of creating an intermediate
42 * {@link Stream} instance
43 */
44 public static @NonNull <T> List<T> filter(@Nullable List<T> list,
45 java.util.function.Predicate<? super T> predicate) {
46 ArrayList<T> result = null;
47 for (int i = 0; i < size(list); i++) {
48 final T item = list.get(i);
49 if (predicate.test(item)) {
50 result = ArrayUtils.add(result, item);
51 }
52 }
53 return emptyIfNull(result);
54 }
55
56 /**
57 * Returns a list of items resulting from applying the given function to each element of the
58 * provided list.
59 *
60 * The resulting list will have the same {@link #size} as the input one.
61 *
62 * This is similar to {@link Stream#map} but without the overhead of creating an intermediate
63 * {@link Stream} instance
64 */
65 public static @NonNull <I, O> List<O> map(@Nullable List<I> cur,
66 Function<? super I, ? extends O> f) {
67 if (cur == null || cur.isEmpty()) return Collections.emptyList();
68 final ArrayList<O> result = new ArrayList<>();
69 for (int i = 0; i < cur.size(); i++) {
70 result.add(f.apply(cur.get(i)));
71 }
72 return result;
73 }
74
75 /**
76 * Returns the given list, or an immutable empty list if the provided list is null
77 *
78 * This can be used to guaranty null-safety without paying the price of extra allocations
79 *
80 * @see Collections#emptyList
81 */
82 public static @NonNull <T> List<T> emptyIfNull(@Nullable List<T> cur) {
83 return cur == null ? Collections.emptyList() : cur;
84 }
85
86 /**
87 * Returns the size of the given list, or 0 if the list is null
88 */
89 public static int size(@Nullable Collection<?> cur) {
90 return cur != null ? cur.size() : 0;
91 }
92
93 /**
94 * Returns the elements of the given list that are of type {@code c}
95 */
96 public static @NonNull <T> List<T> filter(@Nullable List<?> list, Class<T> c) {
97 if (ArrayUtils.isEmpty(list)) return Collections.emptyList();
98 ArrayList<T> result = null;
99 for (int i = 0; i < list.size(); i++) {
100 final Object item = list.get(i);
101 if (c.isInstance(item)) {
102 result = ArrayUtils.add(result, (T) item);
103 }
104 }
105 return emptyIfNull(result);
106 }
107
108 /**
109 * Returns whether there exists at least one element in the list for which
110 * condition {@code predicate} is true
111 */
112 public static <T> boolean any(@Nullable List<T> items,
113 java.util.function.Predicate<T> predicate) {
114 return find(items, predicate) != null;
115 }
116
117 /**
118 * Returns the first element from the list for which
119 * condition {@code predicate} is true, or null if there is no such element
120 */
121 public static @Nullable <T> T find(@Nullable List<T> items,
122 java.util.function.Predicate<T> predicate) {
123 if (ArrayUtils.isEmpty(items)) return null;
124 for (int i = 0; i < items.size(); i++) {
125 final T item = items.get(i);
126 if (predicate.test(item)) return item;
127 }
128 return null;
129 }
Eugene Susla4df89bc2017-03-28 20:27:28 -0700130
131 /**
132 * Similar to {@link List#add}, but with support for list values of {@code null} and
133 * {@link Collections#emptyList}
134 */
135 public static @NonNull <T> List<T> add(@Nullable List<T> cur, T val) {
136 if (cur == null || cur == Collections.emptyList()) {
137 cur = new ArrayList<>();
138 }
139 cur.add(val);
140 return cur;
141 }
142
143 /**
144 * Similar to {@link List#remove}, but with support for list values of {@code null} and
145 * {@link Collections#emptyList}
146 */
147 public static @NonNull <T> List<T> remove(@Nullable List<T> cur, T val) {
148 if (cur == null || cur == Collections.emptyList()) {
149 return Collections.emptyList();
150 }
151 cur.remove(val);
152 return cur;
153 }
154
Eugene Susla6a7006a2017-03-13 12:57:58 -0700155}