| // Copyright (c) 2020, the R8 project authors. Please see the AUTHORS file |
| // for details. All rights reserved. Use of this source code is governed by a |
| // BSD-style license that can be found in the LICENSE file. |
| |
| package com.android.tools.r8.utils; |
| |
| import com.google.common.collect.Iterables; |
| import com.google.common.collect.Iterators; |
| import java.util.ArrayList; |
| import java.util.Collections; |
| import java.util.Comparator; |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.function.BiFunction; |
| import java.util.function.BiPredicate; |
| import java.util.function.Consumer; |
| import java.util.function.Function; |
| import java.util.function.Predicate; |
| |
| public class IterableUtils { |
| |
| public static <S, T> boolean allIdentical(Iterable<S> iterable) { |
| return allIdentical(iterable, Function.identity()); |
| } |
| |
| public static <S, T> boolean allIdentical(Iterable<S> iterable, Function<S, T> fn) { |
| Iterator<S> iterator = iterable.iterator(); |
| if (!iterator.hasNext()) { |
| return true; |
| } |
| T first = fn.apply(iterator.next()); |
| while (iterator.hasNext()) { |
| T other = fn.apply(iterator.next()); |
| if (other != first) { |
| return false; |
| } |
| } |
| return true; |
| } |
| |
| public static <S, T> boolean any( |
| Iterable<S> iterable, Function<S, T> transform, Predicate<T> predicate) { |
| for (S element : iterable) { |
| if (predicate.test(transform.apply(element))) { |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| public static <T> Iterable<T> append(Iterable<T> iterable, T element) { |
| return Iterables.concat(iterable, singleton(element)); |
| } |
| |
| public static <T> List<T> ensureUnmodifiableList(Iterable<T> iterable) { |
| List<T> list; |
| if (iterable instanceof List<?>) { |
| list = (List<T>) iterable; |
| } else { |
| list = toNewArrayList(iterable); |
| } |
| return Collections.unmodifiableList(list); |
| } |
| |
| public static <T> T findOrDefault(Iterable<T> iterable, Predicate<T> predicate, T defaultValue) { |
| for (T element : iterable) { |
| if (predicate.test(element)) { |
| return element; |
| } |
| } |
| return defaultValue; |
| } |
| |
| public static <T> T first(Iterable<T> iterable) { |
| return iterable.iterator().next(); |
| } |
| |
| public static <T> int firstIndexMatching(Iterable<T> iterable, Predicate<T> tester) { |
| int i = 0; |
| for (T element : iterable) { |
| if (tester.test(element)) { |
| return i; |
| } |
| i++; |
| } |
| return -1; |
| } |
| |
| public static <T> Iterable<T> filter(Iterable<T> iterable, Predicate<? super T> predicate) { |
| return () -> IteratorUtils.filter(iterable.iterator(), predicate); |
| } |
| |
| public static <T> boolean hasNext(Iterable<T> iterable) { |
| return iterable.iterator().hasNext(); |
| } |
| |
| public static <T> T min(Iterable<T> iterable, Comparator<T> comparator) { |
| T min = null; |
| for (T element : iterable) { |
| if (min == null || comparator.compare(element, min) < 0) { |
| min = element; |
| } |
| } |
| return min; |
| } |
| |
| public static <T> int size(Iterable<T> iterable) { |
| int result = 0; |
| for (T element : iterable) { |
| result++; |
| } |
| return result; |
| } |
| |
| public static <T> List<T> toNewArrayList(Iterable<T> iterable) { |
| List<T> result = new ArrayList<>(); |
| iterable.forEach(result::add); |
| return result; |
| } |
| |
| public static <S, T> Iterable<T> transform(Iterable<S> iterable, Function<S, T> fn) { |
| return Iterables.transform(iterable, fn::apply); |
| } |
| |
| public static <T> boolean isEmpty(Iterable<T> iterable) { |
| return !iterable.iterator().hasNext(); |
| } |
| |
| public static <T> Iterable<T> singleton(T element) { |
| return () -> Iterators.singletonIterator(element); |
| } |
| |
| public static <T> Iterable<T> prependSingleton(T t, Iterable<T> iterable) { |
| return Iterables.concat(singleton(t), iterable); |
| } |
| |
| public static <T> T reduce(T init, BiFunction<T, T, T> combine, Iterable<? extends T> iterable) { |
| T v = init; |
| for (T t : iterable) { |
| v = combine.apply(v, t); |
| } |
| return v; |
| } |
| |
| public static int sumInt(Iterable<Integer> iterable) { |
| return reduce(0, Integer::sum, iterable); |
| } |
| |
| public static <F> int sumInt(Iterable<F> iterable, Function<? super F, Integer> fn) { |
| Iterable<Integer> integers = Iterables.transform(iterable, fn::apply); |
| return sumInt(integers); |
| } |
| |
| public static <T> Iterable<T> flatten(Iterable<? extends Iterable<T>> iterable) { |
| return flatMap(iterable, Function.identity()); |
| } |
| |
| public static <T, U> Iterable<U> flatMap( |
| Iterable<T> iterable, Function<? super T, Iterable<U>> map) { |
| return Iterables.concat(Iterables.transform(iterable, map::apply)); |
| } |
| |
| public static <T> Iterable<T> empty() { |
| return Collections.emptyList(); |
| } |
| |
| public static <T> Iterable<T> emptyIf(Iterable<T> iterable, boolean condition) { |
| if (condition) { |
| return Collections.emptySet(); |
| } else { |
| return iterable; |
| } |
| } |
| |
| /** |
| * Utility method for testing the the elements in one and other pair-wise. Returns false if the |
| * lengths differ. |
| */ |
| public static <T> boolean testPairs( |
| BiPredicate<T, T> predicate, Iterable<T> one, Iterable<T> other) { |
| Iterator<T> iterator = other.iterator(); |
| for (T first : one) { |
| if (!iterator.hasNext()) { |
| return false; |
| } |
| T second = iterator.next(); |
| if (!predicate.test(first, second)) { |
| return false; |
| } |
| } |
| return !iterator.hasNext(); |
| } |
| |
| public static <T, R> Iterable<R> fromMethod(Consumer<Consumer<T>> method, Function<T, R> mapper) { |
| List<R> ts = new ArrayList<>(); |
| method.accept(t -> ts.add(mapper.apply(t))); |
| return ts; |
| } |
| } |