Add Collections.rotate method emulation
The rotate method implementation based on the Android libcore
implementation picked from j2objc project.
Change-Id: I6b5564545e8112d6e3e1ef4192383969a9c67929
Improvement: issue 9140
diff --git a/user/super/com/google/gwt/emul/java/util/Collections.java b/user/super/com/google/gwt/emul/java/util/Collections.java
index c042f5b..8f6dd2b 100644
--- a/user/super/com/google/gwt/emul/java/util/Collections.java
+++ b/user/super/com/google/gwt/emul/java/util/Collections.java
@@ -1106,6 +1106,58 @@
};
}
+ /**
+ * Rotates the elements in {@code list} by the distance {@code dist}
+ * <p>
+ * e.g. for a given list with elements [1, 2, 3, 4, 5, 6, 7, 8, 9, 0], calling rotate(list, 3) or
+ * rotate(list, -7) would modify the list to look like this: [8, 9, 0, 1, 2, 3, 4, 5, 6, 7]
+ *
+ * @param lst the list whose elements are to be rotated.
+ * @param dist is the distance the list is rotated. This can be any valid integer. Negative values
+ * rotate the list backwards.
+ */
+ @SuppressWarnings("unchecked")
+ public static void rotate(List<?> lst, int dist) {
+ int size = lst.size();
+
+ // Rotating an empty collection results in the same empty collection
+ if (size == 0) {
+ return;
+ }
+
+ // Normalize the distance
+ int normdist = dist % size;
+ if (normdist == 0) {
+ return;
+ }
+ // Transform a rotation to the left into the equivalent rotation to the right.
+ if (normdist < 0) {
+ normdist += size;
+ }
+
+ if (lst instanceof RandomAccess) {
+ List<Object> list = (List<Object>) lst;
+ // Move each element to the new location.
+ Object temp = list.get(0);
+ int index = 0, beginIndex = 0;
+ for (int i = 0; i < size; i++) {
+ index = (index + normdist) % size;
+ temp = list.set(index, temp);
+ if (index == beginIndex) {
+ index = ++beginIndex;
+ temp = list.get(beginIndex);
+ }
+ }
+ } else {
+ int divideIndex = size - normdist;
+ List<?> sublist1 = lst.subList(0, divideIndex);
+ List<?> sublist2 = lst.subList(divideIndex, size);
+ reverse(sublist1);
+ reverse(sublist2);
+ reverse(lst);
+ }
+ }
+
public static <T> Set<T> singleton(T o) {
HashSet<T> set = new HashSet<T>(1);
set.add(o);
diff --git a/user/test/com/google/gwt/emultest/java/util/CollectionsTest.java b/user/test/com/google/gwt/emultest/java/util/CollectionsTest.java
index 4aae793..77c2e1a 100644
--- a/user/test/com/google/gwt/emultest/java/util/CollectionsTest.java
+++ b/user/test/com/google/gwt/emultest/java/util/CollectionsTest.java
@@ -1,12 +1,12 @@
/*
* Copyright 2008 Google Inc.
- *
+ *
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
@@ -15,8 +15,11 @@
*/
package com.google.gwt.emultest.java.util;
+import com.google.gwt.core.client.JavaScriptException;
+
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
@@ -33,6 +36,10 @@
*/
public class CollectionsTest extends EmulTestBase {
+ private interface ListImplProvider {
+ List<Integer> copyOf(Collection<Integer> data);
+ }
+
public static List<Integer> createRandomList() {
ArrayList<Integer> l = new ArrayList<Integer>();
l.add(new Integer(5));
@@ -118,7 +125,7 @@
/**
* Test Collections.binarySearch(List, Object).
- *
+ *
* Verify the following cases: empty List odd numbers of elements even numbers
* of elements not found value larger than all elements not found value
* smaller than all elements
@@ -145,7 +152,7 @@
/**
* Test Collections.binarySearch(List, Object, Comparator).
- *
+ *
* Verify the following cases: empty List odd numbers of elements even numbers
* of elements not found value larger than all elements not found value
* smaller than all elements null Comparator uses natural ordering
@@ -276,6 +283,30 @@
assertEquals(b, createRandomList());
}
+ /**
+ * @tests java.util.Collections#rotate(java.util.List, int)
+ */
+ public void testRotate() {
+ try {
+ Collections.rotate(null, 0);
+ fail("Collections.rotate(null, distance) should throw NullPointerException");
+ } catch (NullPointerException | JavaScriptException expected) {
+ // Expected
+ }
+ // Test optimized RandomAccess code path
+ testRotateImpl(new ListImplProvider() {
+ public List<Integer> copyOf(Collection<Integer> data) {
+ return new ArrayList<>(data);
+ }
+ });
+ // Test sequential List code path
+ testRotateImpl(new ListImplProvider() {
+ public List<Integer> copyOf(Collection<Integer> data) {
+ return new LinkedList<>(data);
+ }
+ });
+ }
+
public void testSort() {
List<String> a = createSortedList();
Collections.reverse(a);
@@ -306,4 +337,35 @@
assertEquals(val, testArray[i]);
}
}
+
+ private void testRotateImpl(ListImplProvider listImpl) {
+ // rotating empty list should not throw exception
+ List<Integer> list = listImpl.copyOf(Collections.<Integer> emptyList());
+ Collections.rotate(list, 2);
+
+ List<Integer> original = Arrays.asList(0, 1, 2, 3, 4);
+ list = listImpl.copyOf(original);
+
+ Collections.rotate(list, 0);
+ assertEquals(original, list);
+
+ Collections.rotate(list, 3);
+ assertEquals(Arrays.asList(2, 3, 4, 0, 1), list);
+
+ Collections.rotate(list, list.size());
+ assertEquals(Arrays.asList(2, 3, 4, 0, 1), list);
+
+ Collections.rotate(list, list.size() + 3);
+ assertEquals(Arrays.asList(4, 0, 1, 2, 3), list);
+
+ Collections.rotate(list, -(list.size() + 3));
+ assertEquals(Arrays.asList(2, 3, 4, 0, 1), list);
+
+ Collections.rotate(list, -list.size());
+ assertEquals(Arrays.asList(2, 3, 4, 0, 1), list);
+
+ Collections.rotate(list, -3);
+ assertEquals(original, list);
+ }
+
}