blob: 500952980baded3fbda1f3007bb72df108341bdd [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to you under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.calcite.linq4j;
import com.google.common.collect.ImmutableList;
import java.util.AbstractList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.RandomAccess;
import java.util.function.ObjIntConsumer;
/**
* Pair of an element and an ordinal.
*
* @param <E> Element type
*/
public class Ord<E> implements Map.Entry<Integer, E> {
public final int i;
public final E e;
/**
* Creates an Ord.
*/
public Ord(int i, E e) {
this.i = i;
this.e = e;
}
/**
* Creates an Ord.
*/
public static <E> Ord<E> of(int n, E e) {
return new Ord<>(n, e);
}
/**
* Creates an iterable of {@code Ord}s over an iterable.
*/
public static <E> Iterable<Ord<E>> zip(final Iterable<? extends E> iterable) {
return () -> zip(iterable.iterator());
}
/**
* Creates an iterator of {@code Ord}s over an iterator.
*/
public static <E> Iterator<Ord<E>> zip(final Iterator<? extends E> iterator) {
return new Iterator<Ord<E>>() {
int n = 0;
public boolean hasNext() {
return iterator.hasNext();
}
public Ord<E> next() {
return Ord.of(n++, iterator.next());
}
public void remove() {
iterator.remove();
}
};
}
/**
* Returns a numbered list based on an array.
*/
public static <E> List<Ord<E>> zip(final E[] elements) {
return new OrdArrayList<>(elements);
}
/**
* Returns a numbered list.
*/
public static <E> List<Ord<E>> zip(final List<? extends E> elements) {
return elements instanceof RandomAccess
? new OrdRandomAccessList<>(elements)
: new OrdList<>(elements);
}
/**
* Iterates over an array in reverse order.
*
* <p>Given the array ["a", "b", "c"], returns (2, "c") then (1, "b") then
* (0, "a").
*/
public static <E> Iterable<Ord<E>> reverse(E... elements) {
return reverse(ImmutableList.copyOf(elements));
}
/**
* Iterates over a list in reverse order.
*
* <p>Given the list ["a", "b", "c"], returns (2, "c") then (1, "b") then
* (0, "a").
*/
public static <E> Iterable<Ord<E>> reverse(Iterable<? extends E> elements) {
final ImmutableList<E> elementList = ImmutableList.copyOf(elements);
return () -> new Iterator<Ord<E>>() {
int i = elementList.size() - 1;
public boolean hasNext() {
return i >= 0;
}
public Ord<E> next() {
return Ord.of(i, elementList.get(i--));
}
public void remove() {
throw new UnsupportedOperationException("remove");
}
};
}
public Integer getKey() {
return i;
}
public E getValue() {
return e;
}
public E setValue(E value) {
throw new UnsupportedOperationException();
}
/** Applies an action to every element of an iterable, passing the zero-based
* ordinal of the element to the action.
*
* @see List#forEach(java.util.function.Consumer)
* @see Map#forEach(java.util.function.BiConsumer)
*
* @param iterable Iterable
* @param action The action to be performed for each element
* @param <T> Element type
*/
public static <T> void forEach(Iterable<T> iterable,
ObjIntConsumer<? super T> action) {
int i = 0;
for (T t : iterable) {
action.accept(t, i++);
}
}
/** Applies an action to every element of an array, passing the zero-based
* ordinal of the element to the action.
*
* @see List#forEach(java.util.function.Consumer)
* @see Map#forEach(java.util.function.BiConsumer)
*
* @param ts Array
* @param action The action to be performed for each element
* @param <T> Element type
*/
public static <T> void forEach(T[] ts,
ObjIntConsumer<? super T> action) {
for (int i = 0; i < ts.length; i++) {
action.accept(ts[i], i);
}
}
/** List of {@link Ord} backed by a list of elements.
*
* @param <E> element type */
private static class OrdList<E> extends AbstractList<Ord<E>> {
private final List<? extends E> elements;
OrdList(List<? extends E> elements) {
this.elements = elements;
}
public Ord<E> get(int index) {
return Ord.of(index, elements.get(index));
}
public int size() {
return elements.size();
}
}
/** List of {@link Ord} backed by a random-access list of elements.
*
* @param <E> element type */
private static class OrdRandomAccessList<E> extends OrdList<E>
implements RandomAccess {
OrdRandomAccessList(List<? extends E> elements) {
super(elements);
}
}
/** List of {@link Ord} backed by an array of elements.
*
* @param <E> element type */
private static class OrdArrayList<E> extends AbstractList<Ord<E>>
implements RandomAccess {
private final E[] elements;
OrdArrayList(E[] elements) {
this.elements = elements;
}
@Override public Ord<E> get(int index) {
return Ord.of(index, elements[index]);
}
@Override public int size() {
return elements.length;
}
}
}