Order
This article mainly studies Iterables of Elasticsearch.
Iterables
elasticsearch-7.0.1/server/src/main/java/org/elasticsearch/common/util/iterable/Iterables.java
public class Iterables {
public static <T> Iterable<T> concat(Iterable<T>... inputs) {
Objects.requireNonNull(inputs);
return new ConcatenatedIterable<>(inputs);
}
static class ConcatenatedIterable<T> implements Iterable<T> {
private final Iterable<T>[] inputs;
ConcatenatedIterable(Iterable<T>[] inputs) {
this.inputs = Arrays.copyOf(inputs, inputs.length);
}
@Override
public Iterator<T> iterator() {
return Stream
.of(inputs)
.map(it -> StreamSupport.stream(it.spliterator(), false))
.reduce(Stream::concat)
.orElseGet(Stream::empty).iterator();
}
}
/** Flattens the two level {@code Iterable} into a single {@code Iterable}. Note that this pre-caches the values from the outer {@code
* Iterable}, but not the values from the inner one. */
public static <T> Iterable<T> flatten(Iterable<? extends Iterable<T>> inputs) {
Objects.requireNonNull(inputs);
return new FlattenedIterables<>(inputs);
}
static class FlattenedIterables<T> implements Iterable<T> {
private final Iterable<? extends Iterable<T>> inputs;
FlattenedIterables(Iterable<? extends Iterable<T>> inputs) {
List<Iterable<T>> list = new ArrayList<>();
for (Iterable<T> iterable : inputs) {
list.add(iterable);
}
this.inputs = list;
}
@Override
public Iterator<T> iterator() {
return StreamSupport
.stream(inputs.spliterator(), false)
.flatMap(s -> StreamSupport.stream(s.spliterator(), false)).iterator();
}
}
public static <T> T get(Iterable<T> iterable, int position) {
Objects.requireNonNull(iterable);
if (position < 0) {
throw new IllegalArgumentException("position >= 0");
}
if (iterable instanceof List) {
List<T> list = (List<T>)iterable;
if (position >= list.size()) {
throw new IndexOutOfBoundsException(Integer.toString(position));
}
return list.get(position);
} else {
Iterator<T> it = iterable.iterator();
for (int index = 0; index < position; index++) {
if (!it.hasNext()) {
throw new IndexOutOfBoundsException(Integer.toString(position));
}
it.next();
}
if (!it.hasNext()) {
throw new IndexOutOfBoundsException(Integer.toString(position));
}
return it.next();
}
}
}
- Iterables provides three static methods: concat, flatten and get, of which concat returns ConcatenatedIterable; ; Flatten returns FlattenedIterables; ; The get method will first determine whether it is of type List. If it is, it will directly return through the position value. If it is not, it will traverse iterable to obtain the element with the specified index.
Example
elasticsearch-7.0.1/server/src/test/java/org/elasticsearch/common/util/iterable/IterablesTests.java
public class IterablesTests extends ESTestCase {
public void testGetOverList() {
test(Arrays.asList("a", "b", "c"));
}
public void testGetOverIterable() {
Iterable<String> iterable = () ->
new Iterator<String>() {
private int position = 0;
@Override
public boolean hasNext() {
return position < 3;
}
@Override
public String next() {
if (position < 3) {
String s = position == 0 ? "a" : position == 1 ? "b" : "c";
position++;
return s;
} else {
throw new NoSuchElementException();
}
}
};
test(iterable);
}
public void testFlatten() {
List<List<Integer>> list = new ArrayList<>();
list.add(new ArrayList<>());
Iterable<Integer> allInts = Iterables.flatten(list);
int count = 0;
for(@SuppressWarnings("unused") int x : allInts) {
count++;
}
assertEquals(0, count);
list.add(new ArrayList<>());
list.get(1).add(0);
// changes to the outer list are not seen since flatten pre-caches outer list on init:
count = 0;
for(@SuppressWarnings("unused") int x : allInts) {
count++;
}
assertEquals(0, count);
// but changes to the original inner lists are seen:
list.get(0).add(0);
for(@SuppressWarnings("unused") int x : allInts) {
count++;
}
assertEquals(1, count);
}
private void test(Iterable<String> iterable) {
try {
Iterables.get(iterable, -1);
fail("expected IllegalArgumentException");
} catch (IllegalArgumentException e) {
assertThat(e, hasToString("java.lang.IllegalArgumentException: position >= 0"));
}
assertEquals("a", Iterables.get(iterable, 0));
assertEquals("b", Iterables.get(iterable, 1));
assertEquals("c", Iterables.get(iterable, 2));
try {
Iterables.get(iterable, 3);
fail("expected IndexOutOfBoundsException");
} catch (IndexOutOfBoundsException e) {
assertThat(e, hasToString("java.lang.IndexOutOfBoundsException: 3"));
}
}
}
- Flatten is used to flat Iterable of Iterable type; The get method gets the element of index specified in iterable
Summary
Iterables provides three static methods: concat, flatten and get, of which concat returns ConcatenatedIterable;; Flatten returns FlattenedIterables;; The get method will first determine whether it is of type List. If it is, it will directly return through the position value. If it is not, it will traverse iterable to obtain the element with the specified index.