diff --git a/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/reflect/ArrayNativeGenerator.java b/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/reflect/ArrayNativeGenerator.java index d56131f9f..a3b9b6a12 100644 --- a/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/reflect/ArrayNativeGenerator.java +++ b/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/reflect/ArrayNativeGenerator.java @@ -124,7 +124,7 @@ public class ArrayNativeGenerator implements Generator, DependencyPlugin { writer.append("return ").appendMethodBody(methodRef).append("(item);").softNewLine(); writer.outdent().append("} else "); } - writer.append("{").softNewLine(); + writer.append("{").indent().softNewLine(); writer.append("return item;").softNewLine(); writer.outdent().append("}").softNewLine(); } diff --git a/teavm-classlib/src/main/java/org/teavm/classlib/java/util/TCollections.java b/teavm-classlib/src/main/java/org/teavm/classlib/java/util/TCollections.java index 21028d7bb..897093a45 100644 --- a/teavm-classlib/src/main/java/org/teavm/classlib/java/util/TCollections.java +++ b/teavm-classlib/src/main/java/org/teavm/classlib/java/util/TCollections.java @@ -15,6 +15,7 @@ */ package org.teavm.classlib.java.util; +import java.util.RandomAccess; import org.teavm.classlib.java.lang.*; /** @@ -156,6 +157,9 @@ public class TCollections extends TObject { } public static void sort(TList list, TComparator c) { + if (c == null) { + c = naturalOrder; + } @SuppressWarnings("unchecked") T[] array = (T[])new Object[list.size()]; list.toArray(array); @@ -166,21 +170,166 @@ public class TCollections extends TObject { } public static > void sort(TList list) { - sort(list, new TComparator() { - @Override public int compare(T o1, T o2) { - return o1 != null ? o1.compareTo(o2) : -o2.compareTo(o1); - } - }); + sort(list, naturalOrder); } public static void reverse(TList list) { + reverse(list, 0, list.size()); + } + + public static int binarySearch(TList> list, T key) { + return binarySearch(list, key, naturalOrder); + } + + private static TComparator naturalOrder = new TComparator() { + @SuppressWarnings("unchecked") @Override public int compare(Object o1, Object o2) { + return o1 != null ? ((TComparable)o1).compareTo(o2) : -((TComparable)o2).compareTo(o1); + } + }; + + public static int binarySearch(TList list, T key, TComparator c) { + if (!(list instanceof TRandomAccess)) { + list = new TArrayList<>(list); + } + if (c == null) { + c = naturalOrder; + } + int l = 0; + int u = list.size() - 1; + while (true) { + int i = (l + u) / 2; + T e = list.get(i); + int cmp = c.compare(key, e); + if (cmp == 0) { + return i; + } else if (cmp < 0) { + u = i - 1; + if (u < l) { + return -i - 1; + } + } else { + l = i + 1; + if (l > u) { + return -i - 2; + } + } + } + } + + public static void shuffle(TList list) { + shuffle(list, new TRandom()); + } + + @SuppressWarnings("unchecked") + public static void shuffle(TList list, TRandom rnd) { + if (list instanceof TRandomAccess) { + shuffleRandomAccess(list, rnd); + } else { + TList randomAccess = new TArrayList<>(list); + shuffleRandomAccess(list, rnd); + list.clear(); + ((TList)list).addAll(randomAccess); + } + } + + private static void shuffleRandomAccess(TList list, TRandom rnd) { + for (int i = list.size() - 1; i > 0; --i) { + int j = rnd.next(i + 1); + swap(list, i, j); + } + } + + public static void fill(TList list, T obj) { + if (list instanceof RandomAccess) { + for (int i = 0; i < list.size(); ++i) { + list.set(i, obj); + } + } else { + for (TListIterator iter = list.listIterator(); iter.hasNext();) { + iter.next(); + iter.set(obj); + } + } + } + + public static void copy(TList dest, TList src) { + if (src.size() > dest.size()) { + throw new IndexOutOfBoundsException(); + } + if (src instanceof RandomAccess && dest instanceof RandomAccess) { + for (int i = 0; i < src.size(); ++i) { + dest.set(i, src.get(i)); + } + } else { + TListIterator srcIter = src.listIterator(); + TListIterator destIter = dest.listIterator(); + while (srcIter.hasNext()) { + destIter.next(); + destIter.set(srcIter.next()); + } + } + } + + public static > T min(TCollection coll) { + return min(coll, naturalOrder); + } + + public static T min(TCollection coll, TComparator comp) { + if (comp == null) { + comp = naturalOrder; + } + TIterator iter = coll.iterator(); + T min = iter.next(); + while (iter.hasNext()) { + T elem = iter.next(); + if (comp.compare(elem, min) < 0) { + min = elem; + } + } + return min; + } + + public static > T max(TCollection coll) { + return max(coll, naturalOrder); + } + + public static T max(TCollection coll, TComparator comp) { + if (comp == null) { + comp = naturalOrder; + } + TIterator iter = coll.iterator(); + T max = iter.next(); + while (iter.hasNext()) { + T elem = iter.next(); + if (comp.compare(elem, max) > 0) { + max = elem; + } + } + return max; + } + + public static void rotate(TList list, int distance) { + distance %= list.size(); + if (distance < 0) { + distance += list.size(); + } + if (distance == 0) { + return; + } + reverse(list, 0, list.size()); + reverse(list, 0, distance); + reverse(list, distance, list.size()); + } + + private static void reverse(TList list, int from, int to) { @SuppressWarnings("unchecked") TList safeList = (TList)list; - int half = safeList.size() / 2; - for (int i = 0; i < half; ++i) { + int half = (from + to) / 2; + int j = to - 1; + for (int i = from; i < half; ++i, --j) { Object tmp = safeList.get(i); - safeList.set(i, safeList.get(safeList.size() - i - 1)); - safeList.set(safeList.size() - i - 1, tmp); + safeList.set(i, safeList.get(j)); + safeList.set(j, tmp); } } } diff --git a/teavm-classlib/src/test/java/org/teavm/classlib/java/util/CollectionsTest.java b/teavm-classlib/src/test/java/org/teavm/classlib/java/util/CollectionsTest.java index 035628771..b12e74dda 100644 --- a/teavm-classlib/src/test/java/org/teavm/classlib/java/util/CollectionsTest.java +++ b/teavm-classlib/src/test/java/org/teavm/classlib/java/util/CollectionsTest.java @@ -15,7 +15,7 @@ */ package org.teavm.classlib.java.util; -import static org.junit.Assert.assertEquals; +import static org.junit.Assert.*; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -27,18 +27,71 @@ import org.junit.Test; * @author Alexey Andreev */ public class CollectionsTest { - private List array; + @Test + public void listSorted() { + List list = new ArrayList<>(); + list.addAll(Arrays.asList(2, 5, 7, 3, 5, 6)); + Collections.sort(list); + assertEquals(Integer.valueOf(2), list.get(0)); + assertEquals(Integer.valueOf(3), list.get(1)); + assertEquals(Integer.valueOf(5), list.get(2)); + assertEquals(Integer.valueOf(5), list.get(3)); + assertEquals(Integer.valueOf(6), list.get(4)); + assertEquals(Integer.valueOf(7), list.get(5)); + } @Test - public void arraySorted() { - array = new ArrayList<>(); - array.addAll(Arrays.asList(2, 5, 7, 3, 5, 6)); - Collections.sort(array); - assertEquals(Integer.valueOf(2), array.get(0)); - assertEquals(Integer.valueOf(3), array.get(1)); - assertEquals(Integer.valueOf(5), array.get(2)); - assertEquals(Integer.valueOf(5), array.get(3)); - assertEquals(Integer.valueOf(6), array.get(4)); - assertEquals(Integer.valueOf(7), array.get(5)); + public void binarySearchWorks() { + List list = new ArrayList<>(Arrays.asList(2, 4, 6, 8, 10, 12, 14, 16)); + assertEquals(3, Collections.binarySearch(list, 8)); + assertEquals(7, Collections.binarySearch(list, 16)); + assertEquals(0, Collections.binarySearch(list, 2)); + assertEquals(-1, Collections.binarySearch(list, 1)); + assertEquals(-2, Collections.binarySearch(list, 3)); + assertEquals(-3, Collections.binarySearch(list, 5)); + assertEquals(-8, Collections.binarySearch(list, 15)); + assertEquals(-9, Collections.binarySearch(list, 17)); + } + + @Test + public void findsMinimum() { + List list = Arrays.asList(6, 5, 7, 3, 5, 6); + assertEquals((Integer)3, Collections.min(list)); + } + + @Test + public void findsMaximum() { + List list = Arrays.asList(6, 5, 7, 3, 5, 6); + assertEquals((Integer)7, Collections.max(list)); + } + + @Test + public void fills() { + List list = new ArrayList<>(Arrays.asList(6, 5, 7, 3, 5, 6)); + Collections.fill(list, 9); + assertEquals(6, list.size()); + assertEquals((Integer)9, list.get(0)); + assertEquals((Integer)9, list.get(5)); + assertEquals((Integer)9, list.get(2)); + } + + @Test + public void copies() { + List list = new ArrayList<>(Arrays.asList(6, 5, 7, 3, 5, 6)); + List dest = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5, 6, 7)); + Collections.copy(dest, list); + assertEquals(7, dest.size()); + assertEquals((Integer)6, dest.get(0)); + assertEquals((Integer)5, dest.get(1)); + assertEquals((Integer)5, dest.get(4)); + assertEquals((Integer)6, dest.get(5)); + assertEquals((Integer)7, dest.get(6)); + } + + @Test + public void rotates() { + List list = new ArrayList<>(Arrays.asList(2, 5, 7, 3, 5, 6)); + Collections.rotate(list, 2); + assertArrayEquals(new Integer[] { 5, 6, 2, 5, 7, 3 }, list.toArray(new Integer[0])); } }