Skip to content

Commit

Permalink
OAK-11112 : added ensure capacity method to collectionutils to create…
Browse files Browse the repository at this point in the history
… collections with expected capacity
  • Loading branch information
Rishabh Kumar committed Sep 12, 2024
1 parent 7d977bb commit 48e873a
Show file tree
Hide file tree
Showing 6 changed files with 53 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@
*/
public class CollectionUtils {

private static final int MAX_CAPACITY = 1 << 30;

private CollectionUtils() {
// no instances for you
}
Expand Down Expand Up @@ -131,12 +133,12 @@ public static <T> Set<T> toSet(@NotNull final T... elements) {
public static <T> Iterable<T> toIterable(@NotNull final Iterator<T> iterator) {
Objects.requireNonNull(iterator);

Iterable<T> delegate = new Iterable<T>() {
return new Iterable<>() {

private boolean consumed = false;

@Override
public Iterator<T> iterator() {
public @NotNull Iterator<T> iterator() {
if (consumed) {
throw new IllegalStateException("Iterator already returned once");
} else {
Expand All @@ -145,8 +147,6 @@ public Iterator<T> iterator() {
}
}
};

return delegate;
}

/**
Expand All @@ -170,7 +170,27 @@ public static <T> Stream<T> toStream(@NotNull Iterable<T> iterable) {
* iterator to convert
* @return the stream (representing the remaining elements in the iterator)
*/
public static <T> Stream<T> toStream(Iterator<T> iterator) {
@NotNull
public static <T> Stream<T> toStream(@NotNull Iterator<T> iterator) {
return StreamSupport.stream(toIterable(iterator).spliterator(), false);
}

/**
* Ensure the capacity of a map or set given the expected number of elements.
*
* @param capacity the expected number of elements
* @return the capacity to use to avoid rehashing & collisions
*/
public static int ensureCapacity(final int capacity) {

if (capacity < 0) {
throw new IllegalArgumentException("Capacity must be non-negative");
}

if (capacity > MAX_CAPACITY) {
return MAX_CAPACITY;
}

return 1 + (int) (capacity / 0.75f);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static org.junit.Assert.fail;

public class CollectionUtilsTest {

final List<String> data = Arrays.asList("one", "two", "three", null);
Expand Down Expand Up @@ -98,7 +100,7 @@ public void iteratorToIIteratable() {
Assert.assertFalse(testit.hasNext());
try {
testit = iterable.iterator();
Assert.fail("should only work once");
fail("should only work once");
} catch (IllegalStateException expected) {
// that's what we want
}
Expand All @@ -112,4 +114,22 @@ public void iteratorToStream() {
List<String> result = stream.collect(Collectors.toList());
Assert.assertEquals(input.toString(), result.toString());
}

@Test
public void ensureCapacity() {
int capacity = CollectionUtils.ensureCapacity(8);
Assert.assertEquals(11, capacity);
}

@Test
public void ensureCapacityWithMaxValue() {
int capacity = CollectionUtils.ensureCapacity(1073741825);
Assert.assertEquals(1073741824, capacity);
}

@Test(expected = IllegalArgumentException.class)
public void ensureCapacityWithNegativeValue() {
int capacity = CollectionUtils.ensureCapacity(-8);
fail("Should throw IllegalArgumentException");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -298,7 +298,7 @@ private Set<String> updateMembers(boolean isRemove, @NotNull String... memberIds
}

// calculate the contentID for each memberId and remember ids that cannot be processed
Map<String, String> updateMap = new HashMap<>((int)Math.ceil(memberIds.length / 0.75));
Map<String, String> updateMap = new HashMap<>(CollectionUtils.ensureCapacity(memberIds.length));
MembershipProvider mp = getMembershipProvider();
for (String memberId : memberIds) {
if (Strings.isNullOrEmpty(memberId)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
import org.apache.jackrabbit.oak.api.Root;
import org.apache.jackrabbit.oak.api.Tree;
import org.apache.jackrabbit.oak.api.Type;
import org.apache.jackrabbit.oak.commons.collections.CollectionUtils;
import org.apache.jackrabbit.oak.namepath.NamePathMapper;
import org.apache.jackrabbit.oak.plugins.identifier.IdentifierManager;
import org.apache.jackrabbit.oak.plugins.memory.PropertyStates;
Expand Down Expand Up @@ -657,7 +658,7 @@ void process() throws RepositoryException {
@NotNull
Map<String, Authorizable> getAuthorizablesToAdd(@NotNull Group gr, @NotNull Map<String, Authorizable> toRemove,
@NotNull Map<String, String> nonExisting) throws RepositoryException {
Map<String, Authorizable> toAdd = new HashMap<>(members.size());
Map<String, Authorizable> toAdd = new HashMap<>(CollectionUtils.ensureCapacity(members.size()));
for (String contentId : members) {
// NOTE: no need to check for re-mapped uuids with the referenceTracker because
// ImportUUIDBehavior.IMPORT_UUID_CREATE_NEW is not supported for user/group imports (see line 189)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import java.util.Set;
import java.util.UUID;

import org.apache.jackrabbit.oak.commons.collections.CollectionUtils;
import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Expand Down Expand Up @@ -130,7 +131,7 @@ void collectReferencedIds(Collection<SegmentId> ids) {

private synchronized Collection<SegmentId> refresh() {
int size = references.size();
Map<SegmentId, WeakReference<SegmentId>> ids = new HashMap<>((int)Math.ceil(size / 0.75));
Map<SegmentId, WeakReference<SegmentId>> ids = new HashMap<>(CollectionUtils.ensureCapacity(size));

boolean hashCollisions = false;
boolean emptyReferences = false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import java.util.zip.CRC32;

import org.apache.jackrabbit.oak.commons.Buffer;
import org.apache.jackrabbit.oak.commons.collections.CollectionUtils;
import org.apache.jackrabbit.oak.segment.util.ReaderAtEnd;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Expand Down Expand Up @@ -93,7 +94,7 @@ public static Buffer loadGraph(ReaderAtEnd readerAtEnd) throws IOException {
public static Map<UUID, List<UUID>> parseGraph(Buffer buffer) {
int nEntries = buffer.getInt(buffer.limit() - 12);

Map<UUID, List<UUID>> graph = new HashMap<>((int)Math.ceil(nEntries / 0.75));
Map<UUID, List<UUID>> graph = new HashMap<>(CollectionUtils.ensureCapacity(nEntries));

for (int i = 0; i < nEntries; i++) {
long msb = buffer.getLong();
Expand Down

0 comments on commit 48e873a

Please sign in to comment.