001/* 002 * SPDX-License-Identifier: Apache-2.0 003 * 004 * Copyright 2024-2026 The Enola <https://enola.dev> Authors 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 * https://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 */ 018package dev.enola.common.collect; 019 020import com.google.common.collect.ImmutableList; 021 022import dev.enola.common.function.CheckedConsumer; 023import dev.enola.common.function.Sneaker; 024 025import java.util.Collection; 026import java.util.OptionalInt; 027 028public final class MoreIterables { 029 030 public static <T, E extends Exception> void forEach( 031 Iterable<T> iterable, CheckedConsumer<T, E> action) throws E { 032 iterable.forEach(Sneaker.sneakyConsumer(action)); 033 } 034 035 /** 036 * Size of an {@link Iterable}, if there is an efficient way of obtaining it. Useful for 037 * optimizations. See also {@link com.google.common.collect.Iterables#size(Iterable)}. 038 */ 039 public static OptionalInt sizeIfKnown(Iterable<?> iterable) { 040 return (iterable instanceof Collection) 041 ? OptionalInt.of(((Collection<?>) iterable).size()) 042 : OptionalInt.empty(); 043 } 044 045 /** 046 * Convert an {@link Iterable} to a {@link Collection}. 047 * 048 * @param iterable an {@link Iterable} (of any kind) 049 * @return Collection which may just be the argument if that {@link Iterable} was a Collection 050 * already (as an optimization), or otherwise an {@link ImmutableList}. Note that this means 051 * that callers should always assume that the returned collection is logically immutable. 052 * Due to the optimization for Iterables that are Collections, we just cannot (efficiently) 053 * actually declare the return type to be an ImmutableCollection. 054 * @param <T> Type 055 */ 056 public static <T> Collection<T> toCollection(Iterable<T> iterable) { 057 if (iterable instanceof Collection<T> collection) return collection; 058 else return ImmutableList.copyOf(iterable); 059 } 060 061 private MoreIterables() {} 062}