序
本文主要研究一下Elasticsearch的Iterables
Iterables
elasticsearch-7.0.1/server/src/main/java/org/elasticsearch/common/util/iterable/Iterables.java
public class Iterables { public staticIterable concat(Iterable ... inputs) { Objects.requireNonNull(inputs); return new ConcatenatedIterable<>(inputs); } static class ConcatenatedIterable implements Iterable { private final Iterable [] inputs; ConcatenatedIterable(Iterable [] inputs) { this.inputs = Arrays.copyOf(inputs, inputs.length); } @Override public Iterator 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 Iterable flatten(Iterable > inputs) { Objects.requireNonNull(inputs); return new FlattenedIterables<>(inputs); } static class FlattenedIterables implements Iterable { private final Iterable > inputs; FlattenedIterables(Iterable > inputs) { List > list = new ArrayList<>(); for (Iterable iterable : inputs) { list.add(iterable); } this.inputs = list; } @Override public Iterator iterator() { return StreamSupport .stream(inputs.spliterator(), false) .flatMap(s -> StreamSupport.stream(s.spliterator(), false)).iterator(); } } public static T get(Iterable iterable, int position) { Objects.requireNonNull(iterable); if (position < 0) { throw new IllegalArgumentException("position >= 0"); } if (iterable instanceof List) { List list = (List )iterable; if (position >= list.size()) { throw new IndexOutOfBoundsException(Integer.toString(position)); } return list.get(position); } else { Iterator 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提供了concat、flatten、get三个静态方法,其中concat返回的是ConcatenatedIterable;flatten返回的是FlattenedIterables;get方法会先判断是否是List类型是的话直接通过position取值返回,不是则遍历iterable获取指定index的元素
实例
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() { Iterableiterable = () -> new Iterator () { 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 = new ArrayList<>(); list.add(new ArrayList<>()); Iterable 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 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用于将Iterable类型的Iterable进行flat操作;get方法则获取iterable中指定index的元素
小结
Iterables提供了concat、flatten、get三个静态方法,其中concat返回的是ConcatenatedIterable;flatten返回的是FlattenedIterables;get方法会先判断是否是List类型是的话直接通过position取值返回,不是则遍历iterable获取指定index的元素