PageRenderTime 52ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/streams-api/src/main/java/com/atlassian/streams/api/common/Iterables.java

https://bitbucket.org/atlassian/atlassian-streams
Java | 463 lines | 320 code | 55 blank | 88 comment | 13 complexity | 5ca4cbe27edf8feb85bb21b226a4d471 MD5 | raw file
  1. package com.atlassian.streams.api.common;
  2. import java.util.Comparator;
  3. import java.util.Iterator;
  4. import java.util.List;
  5. import java.util.NoSuchElementException;
  6. import java.util.TreeSet;
  7. import io.atlassian.util.concurrent.LazyReference;
  8. import com.google.common.base.Function;
  9. import com.google.common.base.Predicate;
  10. import com.google.common.collect.AbstractIterator;
  11. import com.google.common.collect.ImmutableList;
  12. import com.google.common.collect.Iterators;
  13. import com.google.common.collect.Ordering;
  14. import com.google.common.collect.PeekingIterator;
  15. import static com.atlassian.streams.api.common.Option.none;
  16. import static com.atlassian.streams.api.common.Option.some;
  17. import static com.google.common.base.Preconditions.checkArgument;
  18. import static com.google.common.base.Preconditions.checkNotNull;
  19. import static com.google.common.base.Predicates.not;
  20. import static com.google.common.collect.Iterables.concat;
  21. import static com.google.common.collect.Iterables.filter;
  22. import static com.google.common.collect.Iterables.transform;
  23. import static com.google.common.collect.Sets.newTreeSet;
  24. /**
  25. * Useful methods for working with {@link Iterable}s.
  26. */
  27. public final class Iterables
  28. {
  29. private Iterables()
  30. {
  31. throw new UnsupportedOperationException("Cannot be instantiated");
  32. }
  33. /**
  34. * Takes the first {@code n} {@code xs} and returns them.
  35. *
  36. * @param <T> type of {@code xs}
  37. * @param n number of {@code xs} to take
  38. * @param xs list of values
  39. * @return first {@code n} {@code xs}
  40. */
  41. public static <T> Iterable<T> take(final int n, final Iterable<T> xs)
  42. {
  43. checkArgument(n >= 0, "Cannot take a negative number of elements");
  44. if (xs instanceof List)
  45. {
  46. final List<T> list = (List<T>) xs;
  47. return list.subList(0, n < list.size() ? n : list.size());
  48. }
  49. return new Range<T>(0, n, xs);
  50. }
  51. /**
  52. * Drop the first {@code n} {@code xs} and return the rest.
  53. *
  54. * @param <T> type of {@code xs}
  55. * @param n number of {@code xs} to drop
  56. * @param xs list of values
  57. * @return remaining {@code xs} after dropping the first {@code n}
  58. */
  59. public static <T> Iterable<T> drop(final int n, final Iterable<T> xs)
  60. {
  61. checkArgument(n >= 0, "Cannot drop a negative number of elements");
  62. if (xs instanceof List)
  63. {
  64. final List<T> list = (List<T>) xs;
  65. if (n > list.size() - 1)
  66. {
  67. return ImmutableList.of();
  68. }
  69. return ((List<T>) xs).subList(n, list.size());
  70. }
  71. return new Range<T>(n, Integer.MAX_VALUE, xs);
  72. }
  73. static final class Range<T> implements Iterable<T>
  74. {
  75. private final Iterable<T> delegate;
  76. private final int drop;
  77. private final int size;
  78. private Range(final int drop, final int size, final Iterable<T> delegate)
  79. {
  80. this.delegate = checkNotNull(delegate);
  81. this.drop = drop;
  82. this.size = size;
  83. }
  84. public Iterator<T> iterator()
  85. {
  86. return new Iter<T>(drop, size, delegate.iterator());
  87. }
  88. @Override
  89. public String toString()
  90. {
  91. return com.google.common.collect.Iterables.toString(this);
  92. }
  93. static final class Iter<T> extends AbstractIterator<T>
  94. {
  95. private final Iterator<T> it;
  96. private int remaining;
  97. Iter(final int drop, final int size, final Iterator<T> it)
  98. {
  99. this.it = it;
  100. this.remaining = size;
  101. for (int i = 0; i < drop; i++)
  102. {
  103. if (!it.hasNext())
  104. {
  105. break;
  106. }
  107. it.next();
  108. }
  109. }
  110. @Override
  111. protected T computeNext()
  112. {
  113. if ((remaining > 0) && it.hasNext())
  114. {
  115. remaining--;
  116. return it.next();
  117. }
  118. else
  119. {
  120. return endOfData();
  121. }
  122. }
  123. }
  124. }
  125. /**
  126. * Applies {@code f} to each element of {@code collection}, then concatenates the result.
  127. *
  128. * @param <A> type of elements in {@code collection}
  129. * @param <B> type elements in the new {@code Iterable} {@code f} will transform elements to
  130. * @param collection elements to apply {@code f} to
  131. * @param f {@code Function} to apply to elements of {@code collection}
  132. * @return concatenated result of applying {@code f} to each element of {@code collection}
  133. * @deprecated - use java stream API instead
  134. */
  135. @Deprecated
  136. public static <A, B> Iterable<B> flatMap(final Iterable<A> collection, final Function<A, Iterable<B>> f)
  137. {
  138. return concat(transform(collection, f));
  139. }
  140. /**
  141. * Applies each function in {@code fs} to {@code a}.
  142. * @deprecated - use java stream API instead
  143. */
  144. @Deprecated
  145. public static <A, B> Iterable<B> revMap(Iterable<? extends Function<A, B>> fs, A a)
  146. {
  147. return transform(fs, Functions.<A, B>apply(a));
  148. }
  149. /**
  150. * If {@code as} is empty, returns {@code none()}. Otherwise, returns {@code some(get(as, 0))}.
  151. * @param <A> type of elements in {@code as}
  152. * @param as elements to get the first value of
  153. * @return {@code none()} if {@code as} is empty. {@code some(get(as, 0))} otherwise
  154. */
  155. public static <A> Option<A> first(final Iterable<A> as)
  156. {
  157. final Iterator<A> i = as.iterator();
  158. if (!i.hasNext())
  159. {
  160. return none();
  161. }
  162. return some(i.next());
  163. }
  164. /**
  165. * @return {@code Predicate} which checks if an {@code Iterable} is empty
  166. * @deprecated - use java streams api instead
  167. */
  168. @Deprecated
  169. public static Predicate<Iterable<?>> isEmpty()
  170. {
  171. return new Predicate<Iterable<?>>()
  172. {
  173. public boolean apply(final Iterable<?> i)
  174. {
  175. return com.google.common.collect.Iterables.isEmpty(i);
  176. }
  177. };
  178. }
  179. /**
  180. * Merge a number of already sorted collections of elements into a single collection of elements, using the elements
  181. * natural ordering.
  182. *
  183. * @param <A> type of the elements
  184. * @param xss collection of already sorted collections
  185. * @return {@code xss} merged in a sorted order
  186. */
  187. public static <A extends Comparable<A>> Iterable<A> mergeSorted(final Iterable<? extends Iterable<A>> xss)
  188. {
  189. return mergeSorted(xss, Ordering.<A> natural());
  190. }
  191. /**
  192. * Merge a number of already sorted collections of elements into a single collection of elements.
  193. *
  194. * @param <A> type of the elements
  195. * @param xss already sorted collection of collections
  196. * @param ordering ordering to use when comparing elements
  197. * @return {@code xss} merged in a sorted order
  198. */
  199. public static <A> Iterable<A> mergeSorted(final Iterable<? extends Iterable<A>> xss, final Ordering<A> ordering)
  200. {
  201. return new MergeSortedIterable<A>(xss, ordering);
  202. }
  203. public static <A> Iterable<A> mergeSorted(final Iterable<? extends Iterable<A>> xss, final Comparator<A> comparator)
  204. {
  205. return new MergeSortedIterable<A>(xss, comparator);
  206. }
  207. private static final class MergeSortedIterable<A> implements Iterable<A>
  208. {
  209. private final Iterable<? extends Iterable<A>> xss;
  210. private final Comparator<A> ordering;
  211. /**
  212. * @deprecated use {@link #MergeSortedIterable(Iterable, Comparator)} instead
  213. */
  214. @Deprecated
  215. public MergeSortedIterable(final Iterable<? extends Iterable<A>> xss, final Ordering<A> ordering)
  216. {
  217. this.xss = checkNotNull(xss, "xss");
  218. this.ordering = checkNotNull(ordering, "ordering");
  219. }
  220. public MergeSortedIterable(final Iterable<? extends Iterable<A>> xss, final Comparator<A> ordering)
  221. {
  222. this.xss = checkNotNull(xss, "xss");
  223. this.ordering = checkNotNull(ordering, "ordering");
  224. }
  225. public Iterator<A> iterator()
  226. {
  227. return new Iter<A>(xss, ordering);
  228. }
  229. @Override
  230. public String toString()
  231. {
  232. return com.google.common.collect.Iterables.toString(this);
  233. }
  234. private static final class Iter<A> extends AbstractIterator<A>
  235. {
  236. private final TreeSet<PeekingIterator<A>> xss;
  237. private Iter(final Iterable<? extends Iterable<A>> xss, final Comparator<A> ordering)
  238. {
  239. this.xss = newTreeSet(peekingIteratorOrdering(ordering));
  240. com.google.common.collect.Iterables.addAll(this.xss, transform(filter(xss, not(isEmpty())), peekingIterator()));
  241. }
  242. @Override
  243. protected A computeNext()
  244. {
  245. final Option<PeekingIterator<A>> currFirstOption = first(xss);
  246. if (!currFirstOption.isDefined())
  247. {
  248. return endOfData();
  249. }
  250. final PeekingIterator<A> currFirst = currFirstOption.get();
  251. // We remove the iterator from the set first, before we mutate it, otherwise we wouldn't be able to
  252. // properly find it to remove it. Mutation sucks.
  253. xss.remove(currFirst);
  254. final A next = currFirst.next();
  255. if (currFirst.hasNext())
  256. {
  257. xss.add(currFirst);
  258. }
  259. return next;
  260. }
  261. private Function<? super Iterable<A>, ? extends PeekingIterator<A>> peekingIterator()
  262. {
  263. return new Function<Iterable<A>, PeekingIterator<A>>()
  264. {
  265. public PeekingIterator<A> apply(final Iterable<A> i)
  266. {
  267. return Iterators.peekingIterator(i.iterator());
  268. }
  269. };
  270. }
  271. private Ordering<? super PeekingIterator<A>> peekingIteratorOrdering(final Comparator<A> ordering)
  272. {
  273. return new Ordering<PeekingIterator<A>>()
  274. {
  275. public int compare(final PeekingIterator<A> lhs, final PeekingIterator<A> rhs)
  276. {
  277. if (lhs == rhs)
  278. {
  279. return 0;
  280. }
  281. return ordering.compare(lhs.peek(), rhs.peek());
  282. }
  283. };
  284. }
  285. }
  286. }
  287. /**
  288. * Makes a lazy copy of {@code xs}.
  289. *
  290. * @param <A> type of elements in {@code xs}
  291. * @param xs {@code Iterable} to be memoized
  292. * @return lazy copy of {@code as}
  293. */
  294. public static <A> Iterable<A> memoize(final Iterable<A> xs)
  295. {
  296. return new Memoizer<A>(xs);
  297. }
  298. /**
  299. * Memoizing iterable, maintains a lazily computed linked list of nodes.
  300. *
  301. * @param <A> the type
  302. */
  303. static final class Memoizer<A> implements Iterable<A>
  304. {
  305. private final Node<A> head;
  306. Memoizer(final Iterable<A> delegate)
  307. {
  308. head = nextNode(delegate.iterator());
  309. }
  310. public Iterator<A> iterator()
  311. {
  312. return new Iter<A>(head);
  313. }
  314. @Override
  315. public String toString()
  316. {
  317. return com.google.common.collect.Iterables.toString(this);
  318. }
  319. private static <A> Node<A> nextNode(final Iterator<A> delegate)
  320. {
  321. return delegate.hasNext() ? new Lazy<A>(delegate) : new End<A>();
  322. }
  323. /**
  324. * Linked list node.
  325. */
  326. interface Node<A>
  327. {
  328. boolean isEnd();
  329. A value();
  330. /**
  331. * Get the next Node.
  332. *
  333. * @return a new Node
  334. * @throws NoSuchElementException if this is terminal
  335. */
  336. Node<A> next() throws NoSuchElementException;
  337. }
  338. /**
  339. * Lazily computes the next node. Has a value so is not an end.
  340. */
  341. static class Lazy<A> extends LazyReference<Node<A>> implements Node<A>
  342. {
  343. private final Iterator<A> delegate;
  344. private final A value;
  345. Lazy(final Iterator<A> delegate)
  346. {
  347. this.delegate = delegate;
  348. this.value = delegate.next();
  349. }
  350. @Override
  351. protected Node<A> create() throws Exception
  352. {
  353. return nextNode(delegate);
  354. }
  355. public Node<A> next() throws NoSuchElementException
  356. {
  357. return get();
  358. }
  359. public boolean isEnd()
  360. {
  361. return false;
  362. }
  363. public A value()
  364. {
  365. return value;
  366. }
  367. }
  368. static class End<A> implements Node<A>
  369. {
  370. public boolean isEnd()
  371. {
  372. return true;
  373. }
  374. public Node<A> next()
  375. {
  376. throw new NoSuchElementException();
  377. }
  378. public A value()
  379. {
  380. throw new NoSuchElementException();
  381. }
  382. }
  383. static class Iter<A> extends AbstractIterator<A>
  384. {
  385. Node<A> node;
  386. Iter(final Node<A> node)
  387. {
  388. this.node = node;
  389. }
  390. @Override
  391. protected A computeNext()
  392. {
  393. if (node.isEnd())
  394. {
  395. return endOfData();
  396. }
  397. try
  398. {
  399. return node.value();
  400. }
  401. finally
  402. {
  403. node = node.next();
  404. }
  405. }
  406. }
  407. }
  408. }