Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
org.neo4j.internal.helpers.collection.Iterables Maven / Gradle / Ivy
/*
* Copyright (c) "Neo4j"
* Neo4j Sweden AB [https://neo4j.com]
*
* This file is part of Neo4j.
*
* Neo4j is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
package org.neo4j.internal.helpers.collection;
import static java.util.Objects.requireNonNull;
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.Set;
import java.util.Spliterator;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Stream;
import org.neo4j.function.Predicates;
import org.neo4j.function.ThrowingConsumer;
import org.neo4j.graphdb.Resource;
import org.neo4j.graphdb.ResourceIterable;
import org.neo4j.graphdb.ResourceIterator;
import org.neo4j.internal.helpers.Exceptions;
/**
* Utility methods for processing iterables. Where possible, If the iterable implements
* {@link Resource}, it will be {@link Resource#close() closed} when the processing
* has been completed.
*/
public final class Iterables {
private Iterables() {
throw new AssertionError("no instance");
}
public static Iterable empty() {
return Collections.emptyList();
}
@SuppressWarnings("unchecked")
public static ResourceIterable emptyResourceIterable() {
return (ResourceIterable) EmptyResourceIterable.EMPTY_RESOURCE_ITERABLE;
}
/**
* Collect all the elements available in {@code iterable} and add them to the
* provided {@code collection}.
*
* If the {@code iterable} implements {@link Resource} it will be
* {@link Resource#close() closed} in a {@code finally} block after all
* the items have been added.
*
* @param collection the collection to add items to.
* @param iterable the iterable from which items will be collected
* @param the type of elements in {@code iterable}.
* @param the type of the collection to add the items to.
* @return the {@code collection} that has been updated.
*/
public static > C addAll(C collection, Iterable extends T> iterable) {
try {
Iterator extends T> iterator = iterable.iterator();
try {
while (iterator.hasNext()) {
collection.add(iterator.next());
}
} finally {
Iterators.tryCloseResource(iterator);
}
} finally {
tryCloseResource(iterable);
}
return collection;
}
public static Iterable filter(Predicate super X> specification, Iterable i) {
return new FilterIterable<>(i, specification);
}
public static List reverse(List iterable) {
List list = asList(iterable);
Collections.reverse(list);
return list;
}
public static Iterable map(Function super FROM, ? extends TO> function, Iterable from) {
return new MapIterable<>(from, function);
}
@SafeVarargs
public static Iterable iterable(C... items) {
return Arrays.asList(items);
}
@SuppressWarnings("unchecked")
public static Iterable cast(Iterable iterable) {
return (Iterable) iterable;
}
@SafeVarargs
@SuppressWarnings("unchecked")
public static Iterable concat(Iterable extends T>... iterables) {
return concat(Arrays.asList((Iterable[]) iterables));
}
public static Iterable concat(final Iterable extends Iterable> iterables) {
return new CombiningIterable<>(iterables);
}
public static Iterable append(final C item, final Iterable iterable) {
return () -> {
final Iterator iterator = iterable.iterator();
return new Iterator<>() {
T last = item;
@Override
public boolean hasNext() {
return iterator.hasNext() || last != null;
}
@Override
public T next() {
if (iterator.hasNext()) {
return iterator.next();
}
try {
return last;
} finally {
last = null;
}
}
@Override
public void remove() {}
};
};
}
public static Object[] asArray(Iterable iterable) {
return asArray(Object.class, iterable);
}
@SuppressWarnings("unchecked")
public static T[] asArray(Class componentType, Iterable iterable) {
if (iterable == null) {
return null;
}
List list = asList(iterable);
return list.toArray((T[]) Array.newInstance(componentType, list.size()));
}
public static ResourceIterable asResourceIterable(final Iterable iterable) {
if (iterable instanceof ResourceIterable>) {
return (ResourceIterable) iterable;
}
return new AbstractResourceIterable<>() {
@Override
protected ResourceIterator newIterator() {
return Iterators.asResourceIterator(iterable.iterator());
}
@Override
protected void onClosed() {
tryCloseResource(iterable);
}
};
}
/**
* Returns the given iterable's first element or {@code null} if no
* element found.
*
* If the {@code iterable} implements {@link Resource}, then it will be closed in a {@code finally} block
* after the items have been joined.
*
* If the {@link Iterable#iterator() iterator} created by the {@code iterable} implements {@link Resource}
* it will be {@link Resource#close() closed} in a {@code finally} block after the items have been joined.
*
* @param values the {@link Iterable} to get elements from.
* @param separator the separator to use between the items in {@code values}.
* @return the joined string.
*/
public static String toString(Iterable> values, String separator) {
Iterator> it = values.iterator();
try {
StringBuilder sb = new StringBuilder();
while (it.hasNext()) {
sb.append(it.next());
if (it.hasNext()) {
sb.append(separator);
}
}
return sb.toString();
} finally {
Iterators.tryCloseResource(it);
tryCloseResource(values);
}
}
/**
* Returns the given iterable's first element or {@code null} if no
* element found.
*
* If the {@code iterable} implements {@link Resource}, then it will be closed in a {@code finally} block
* after the first item has been retrieved, or failed to be retrieved.
*
* If the {@link Iterable#iterator() iterator} created by the {@code iterable} implements {@link Resource}
* it will be {@link Resource#close() closed} in a {@code finally} block after the single item
* has been retrieved, or failed to be retrieved.
*
* @param the type of elements in {@code iterable}.
* @param iterable the {@link Iterable} to get elements from.
* @return the first element in the {@code iterable}, or {@code null} if no
* element found.
*/
public static T firstOrNull(Iterable iterable) {
try {
return Iterators.firstOrNull(iterable.iterator());
} finally {
tryCloseResource(iterable);
}
}
/**
* Returns the given iterable's first element. If no element is found a
* {@link NoSuchElementException} is thrown.
*
* If the {@code iterable} implements {@link Resource}, then it will be closed in a {@code finally} block
* after the first item has been retrieved, or failed to be retrieved.
*
* @param the type of elements in {@code iterable}.
* @param iterable the {@link Iterable} to get elements from.
* @return the first element in the {@code iterable}.
* @throws NoSuchElementException if no element found.
*/
public static T first(Iterable iterable) {
try {
return Iterators.first(iterable.iterator());
} finally {
tryCloseResource(iterable);
}
}
/**
* Returns the given iterable's last element. If no element is found a
* {@link NoSuchElementException} is thrown.
*
* If the {@code iterable} implements {@link Resource}, then it will be closed in a {@code finally} block
* after the last item has been retrieved, or failed to be retrieved.
*
* @param the type of elements in {@code iterable}.
* @param iterable the {@link Iterable} to get elements from.
* @return the last element in the {@code iterable}.
* @throws NoSuchElementException if no element found.
*/
public static T last(Iterable iterable) {
try {
return Iterators.last(iterable.iterator());
} finally {
tryCloseResource(iterable);
}
}
/**
* Returns the given iterable's single element or {@code null} if no
* element found. If there is more than one element in the iterable a
* {@link NoSuchElementException} will be thrown.
*
* If the {@code iterable} implements {@link Resource}, then it will be closed in a {@code finally} block
* after the single item has been retrieved, or failed to be retrieved.
*
* If the {@link Iterable#iterator() iterator} created by the {@code iterable} implements {@link Resource}
* it will be {@link Resource#close() closed} in a {@code finally} block after the single item
* has been retrieved, or failed to be retrieved.
*
* @param the type of elements in {@code iterable}.
* @param iterable the {@link Iterable} to get elements from.
* @return the single element in {@code iterable}, or {@code null} if no
* element found.
* @throws NoSuchElementException if more than one element was found.
*/
public static T singleOrNull(Iterable iterable) {
try {
return Iterators.singleOrNull(iterable.iterator());
} finally {
tryCloseResource(iterable);
}
}
/**
* Returns the given iterable's single element. If there are no elements
* or more than one element in the iterable a {@link NoSuchElementException}
* will be thrown.
*
* If the {@code iterable} implements {@link Resource}, then it will be closed in a {@code finally} block
* after the single item has been retrieved, or failed to be retrieved.
*
* If the {@link Iterable#iterator() iterator} created by the {@code iterable} implements {@link Resource}
* it will be {@link Resource#close() closed} in a {@code finally} block after the single item
* has been retrieved, or failed to be retrieved.
*
* @param the type of elements in {@code iterable}.
* @param iterable the {@link Iterable} to get elements from.
* @return the single element in the {@code iterable}.
* @throws NoSuchElementException if there isn't exactly one element.
*/
public static T single(Iterable iterable) {
try {
return Iterators.single(iterable.iterator());
} finally {
tryCloseResource(iterable);
}
}
/**
* Returns the given iterable's single element or {@code itemIfNone} if no
* element found. If there is more than one element in the iterable a
* {@link NoSuchElementException} will be thrown.
*
* If the {@code iterable} implements {@link Resource}, then it will be closed in a {@code finally} block
* after the single item has been retrieved, or failed to be retrieved.
*
>
* If the {@link Iterable#iterator() iterator} created by the {@code iterable} implements {@link Resource}
* it will be {@link Resource#close() closed} in a {@code finally} block after the single item
* has been retrieved, or failed to be retrieved.
*
* @param the type of elements in {@code iterable}.
* @param iterable the {@link Iterable} to get elements from.
* @param itemIfNone item to use if none is found
* @return the single element in {@code iterable}, or {@code null} if no
* element found.
* @throws NoSuchElementException if more than one element was found.
*/
public static T single(Iterable iterable, T itemIfNone) {
try {
return Iterators.single(iterable.iterator(), itemIfNone);
} finally {
tryCloseResource(iterable);
}
}
/**
* Counts the number of items in the {@code iterable} by looping through it.
*
* If the {@code iterable} implements {@link Resource}, then it will be closed in a {@code finally} block
* after all its items have been counted.
*
* If the {@link Iterable#iterator() iterator} created by the {@code iterable} implements {@link Resource}
* it will be {@link Resource#close() closed} in a {@code finally} block after the items have been counted.
*
* @param the type of items in the iterator.
* @param iterable the {@link Iterable} to count items in.
* @return the number of items found in {@code iterable}.
*/
public static long count(Iterable iterable) {
return count(iterable, Predicates.alwaysTrue());
}
/**
* Counts the number of filtered items in the {@code iterable} by looping through it.
*
* If the {@code iterable} implements {@link Resource}, then it will be closed in a {@code finally} block
* after all its items have been counted.
*
* If the {@link Iterable#iterator() iterator} created by the {@code iterable} implements {@link Resource}
* it will be {@link Resource#close() closed} in a {@code finally} block after the items have been counted.
*
* @param the type of items in the iterator.
* @param iterable the {@link Iterable} to count items in.
* @param filter the filter to test items against
* @return the number of found in {@code iterable}.
*/
public static long count(Iterable iterable, Predicate filter) {
try {
return Iterators.count(iterable.iterator(), filter);
} finally {
tryCloseResource(iterable);
}
}
/**
* Creates a collection from an iterable.
*
* If the {@code iterable} implements {@link Resource}, then it will be closed in a {@code finally} block
* after all its items have been added.
*
* If the {@link Iterable#iterator() iterator} created by the {@code iterable} implements {@link Resource}
* it will be {@link Resource#close() closed} in a {@code finally} block after all the items have been added.
*
* @param iterable The iterable to create the collection from.
* @param The generic type of both the iterable and the collection.
* @return a collection containing all items from the iterable.
*/
public static Collection asCollection(Iterable iterable) {
return addAll(new ArrayList<>(), iterable);
}
/**
* Creates a list from an iterable.
*
* If the {@code iterable} implements {@link Resource}, then it will be closed in a {@code finally} block
* after all its items have been added.
*
* If the {@link Iterable#iterator() iterator} created by the {@code iterable} implements {@link Resource}
* it will be {@link Resource#close() closed} in a {@code finally} block after all the items have been added.
*
* @param iterable The iterable to create the list from.
* @param The generic type of both the iterable and the list.
* @return a list containing all items from the iterable.
*/
public static List asList(Iterable iterable) {
return addAll(new ArrayList<>(), iterable);
}
/**
* Creates a {@link Set} from an {@link Iterable}.
*
* If the {@code iterable} implements {@link Resource}, then it will be closed in a {@code finally} block
* after all its items have been added.
*
* If the {@link Iterable#iterator() iterator} created by the {@code iterable} implements {@link Resource}
* it will be {@link Resource#close() closed} in a {@code finally} block after all the items have been added.
*
* @param iterable The items to create the set from.
* @param The generic type of items.
* @return a set containing all items from the {@link Iterable}.
*/
public static Set asSet(Iterable iterable) {
return addAll(new HashSet<>(), iterable);
}
/**
* Creates a {@link Set} from an {@link Iterable}.
*
* If the {@code iterable} implements {@link Resource}, then it will be closed in a {@code finally} block
* after all its items have been added.
*
* @param iterable The items to create the set from.
* @param The generic type of items.
* @return a set containing all items from the {@link Iterable}.
*/
public static Set asUniqueSet(Iterable iterable) {
try {
return Iterators.addToCollectionUnique(iterable, new HashSet<>());
} finally {
tryCloseResource(iterable);
}
}
public static Iterable asIterable(final long... array) {
return () -> Iterators.asIterator(array);
}
public static Iterable asIterable(final int... array) {
return () -> Iterators.asIterator(array);
}
@SafeVarargs
public static Iterable asIterable(final T... array) {
return () -> Iterators.iterator(array);
}
public static ResourceIterable resourceIterable(final Iterable iterable) {
return new AbstractResourceIterable<>() {
@Override
protected ResourceIterator newIterator() {
Iterator iterator = iterable.iterator();
Resource resource = (iterator instanceof Resource) ? (Resource) iterator : Resource.EMPTY;
return Iterators.resourceIterator(iterator, resource);
}
@Override
protected void onClosed() {
tryCloseResource(iterable);
}
};
}
public static Iterable option(final T item) {
if (item == null) {
return Collections.emptyList();
}
return () -> Iterators.iterator(item);
}
/**
* Create a stream from the given iterable.
*
* Note: returned stream needs to be closed via {@link Stream#close()} if the given iterable implements
* {@link Resource}.
*
* @param iterable the iterable to convert to stream
* @param the type of elements in the given iterable
* @return stream over the iterable elements
* @throws NullPointerException when the given iterable is {@code null}
*/
public static Stream stream(Iterable iterable) {
return stream(iterable, 0);
}
/**
* Create a stream from the given iterable with given characteristics.
*
* Note: returned stream needs to be closed via {@link Stream#close()} if the given iterable implements
* {@link Resource}.
*
* @param iterable the iterable to convert to stream
* @param characteristics the logical OR of characteristics for the underlying {@link Spliterator}
* @param the type of elements in the given iterable
* @return stream over the iterable elements
* @throws NullPointerException when the given iterable is {@code null}
*/
public static Stream stream(Iterable iterable, int characteristics) {
requireNonNull(iterable);
return Iterators.stream(iterable.iterator(), characteristics).onClose(() -> tryCloseResource(iterable));
}
/**
* Method for calling a lambda function on many objects. The first exception to be encountered will be
* thrown and subsequent processing of the remaining items will be aborted.
*
* If the {@code iterable} implements {@link Resource}, then it will be closed in a {@code finally} block
* after all its items have been consumed.
*
* @param iterable iterable to iterate over
* @param consumer lambda function to call on each object passed
*/
public static void forEach(Iterable iterable, Consumer consumer) {
try {
for (final var item : iterable) {
consumer.accept(item);
}
} finally {
tryCloseResource(iterable);
}
}
/**
* Method for calling a lambda function on many objects when it is expected that the function might
* throw an exception. First exception will be thrown and subsequent will be suppressed.
* This method guarantees that all subjects will be consumed, unless {@link Error} happens.
*
* @param the type of exception anticipated, inferred from the lambda
* @param subjects {@link Iterable} of objects to call the function on
* @param consumer lambda function to call on each object passed
* @throws E if consumption fails with this exception
*/
@SuppressWarnings("unchecked")
public static void safeForAll(Iterable subjects, ThrowingConsumer consumer)
throws E {
try {
E exception = null;
for (T instance : subjects) {
try {
consumer.accept(instance);
} catch (Throwable t) {
exception = Exceptions.chain(exception, (E) t);
}
}
if (exception != null) {
throw exception;
}
} finally {
tryCloseResource(subjects);
}
}
public static List union(List list1, List list2) {
requireNonNull(list1);
requireNonNull(list2);
var result = new ArrayList(list1.size() + list2.size());
result.addAll(list1);
result.addAll(list2);
return result;
}
/**
* Close the provided {@code iterable} if it implements {@link Resource}.
*
* @param iterable the iterable to check for closing
*/
public static void tryCloseResource(Iterable> iterable) {
if (iterable instanceof Resource closeable) {
closeable.close();
}
}
private static class EmptyResourceIterable implements ResourceIterable {
private static final ResourceIterable EMPTY_RESOURCE_ITERABLE = new EmptyResourceIterable<>();
@Override
public ResourceIterator iterator() {
return Iterators.emptyResourceIterator();
}
@Override
public void close() {
// no-op
}
}
}