LimitedInMemorySortedIterable implements Iterable<E> { public boolean add(final E e) { boolean result = false; final OneOrMore<E> values = backingMap.get(e); boolean skipItem = (deduplicate && null != values && values.contains(e)); if (!skipItem) { if (null != limit && size >= limit) { final Map.Entry<E, OneOrMore<E>> last = backingMap.lastEntry(); if (0 < comparator.compare(last.getKey(), e)) { if (1 < last.getValue().size()) { last.getValue().removeAnyItem(); } else { backingMap.remove(last.getKey()); } size--; } else { skipItem = true; } } if (!skipItem) { if (null == values) { backingMap.put(e, new OneOrMore<>(deduplicate, e)); size++; result = true; } else if (values.add(e)) { size++; result = true; } } } return result; } LimitedInMemorySortedIterable(final Comparator<E> comparator);  LimitedInMemorySortedIterable(final Comparator<E> comparator, final Integer limit);  LimitedInMemorySortedIterable(final Comparator<E> comparator, final Integer limit, final boolean deduplicate); boolean add(final E e); boolean addAll(final Iterable<E> items); int size(); @Override Iterator<E> iterator(); @Override boolean equals(final Object obj); @Override int hashCode(); @Override String toString();  }
@Test public void shouldLimitEntries() { final LimitedInMemorySortedIterable<Integer> list = new LimitedInMemorySortedIterable<Integer>(Comparator.naturalOrder(), 100); final List<Integer> expectedItems = new ArrayList<>(); IntStream.rangeClosed(1, 100).forEach(expectedItems::add); for (int i = 200; 0 < i; i--) { list.add(i); } assertEquals(expectedItems, Lists.newArrayList(list)); }
@Test public void shouldLimitAndDeduplicateEntries() { final LimitedInMemorySortedIterable<Integer> list = new LimitedInMemorySortedIterable<Integer>(Comparator.naturalOrder(), 2, true); list.add(1); list.add(1); list.add(2); list.add(1); list.add(2); list.add(10); assertEquals(Arrays.asList(1, 2), Lists.newArrayList(list)); }
@Test public void shouldDeduplicateEntries() { final LimitedInMemorySortedIterable<Integer> list = new LimitedInMemorySortedIterable<Integer>(Comparator.naturalOrder(), 100, true); list.add(1); list.add(1); assertEquals(Collections.singletonList(1), Lists.newArrayList(list)); }
@Test public void shouldNotDeduplicateEntries() { final LimitedInMemorySortedIterable<Integer> list = new LimitedInMemorySortedIterable<Integer>(Comparator.naturalOrder(), 100, false); list.add(1); list.add(1); assertEquals(Arrays.asList(1, 1), Lists.newArrayList(list)); }
@Test public void shouldLimitAndNotDeduplicateEntries() { final LimitedInMemorySortedIterable<Integer> list = new LimitedInMemorySortedIterable<Integer>(Comparator.naturalOrder(), 4, false); list.add(1); list.add(2); list.add(1); list.add(2); list.add(10); assertEquals(Arrays.asList(1, 1, 2, 2), Lists.newArrayList(list)); }
@Test public void shouldSortLargeNumberOfItems() { final int streamSize = 1000000; final int resultLimit = 10000; final IntStream stream = new Random() .ints(streamSize * 2) .distinct() .limit(streamSize); final LimitedInMemorySortedIterable<Integer> list = new LimitedInMemorySortedIterable<Integer>(Comparator.naturalOrder(), resultLimit, false); stream.forEach(i -> list.add(Math.abs(i))); final List<Integer> sortedElements = Lists.newArrayList(list); sortedElements.sort(Comparator.naturalOrder()); final List<Integer> expected = Lists.newArrayList(list); assertEquals(expected, sortedElements); }