mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 16:14:10 -08:00
classlib: fix issues related to ArrayList, Arrays and Comparator
This commit is contained in:
parent
c5572bc573
commit
a1074918cf
|
@ -99,8 +99,7 @@ public abstract class TAbstractList<E> extends TAbstractCollection<E> implements
|
||||||
public int indexOf(Object o) {
|
public int indexOf(Object o) {
|
||||||
int sz = size();
|
int sz = size();
|
||||||
for (int i = 0; i < sz; ++i) {
|
for (int i = 0; i < sz; ++i) {
|
||||||
Object e = get(i);
|
if (TObjects.equals(o, get(i))) {
|
||||||
if (o == null ? e == null : o.equals(e)) {
|
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -111,8 +110,7 @@ public abstract class TAbstractList<E> extends TAbstractCollection<E> implements
|
||||||
public int lastIndexOf(Object o) {
|
public int lastIndexOf(Object o) {
|
||||||
int sz = size();
|
int sz = size();
|
||||||
for (int i = sz - 1; i >= 0; --i) {
|
for (int i = sz - 1; i >= 0; --i) {
|
||||||
Object e = get(i);
|
if (TObjects.equals(o, get(i))) {
|
||||||
if (o == null ? e == null : o.equals(e)) {
|
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -129,6 +129,7 @@ public class TArrayList<E> extends TAbstractList<E> implements TCloneable, TSeri
|
||||||
public void clear() {
|
public void clear() {
|
||||||
Arrays.fill(array, 0, size, null);
|
Arrays.fill(array, 0, size, null);
|
||||||
size = 0;
|
size = 0;
|
||||||
|
++modCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -210,4 +211,10 @@ public class TArrayList<E> extends TAbstractList<E> implements TCloneable, TSeri
|
||||||
buffer.append(array[length] == this ? "(this Collection)" : array[length]);
|
buffer.append(array[length] == this ? "(this Collection)" : array[length]);
|
||||||
return buffer.append(']').toString();
|
return buffer.append(']').toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void sort(TComparator<? super E> comp) {
|
||||||
|
TArrays.sort(array, 0, size, comp);
|
||||||
|
modCount++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -912,27 +912,17 @@ public class TArrays extends TObject {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void sort(Object[] a) {
|
public static void sort(Object[] a) {
|
||||||
sort(a, new NaturalOrder());
|
sort(a, TComparator.NaturalOrder.instance());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void sort(Object[] a, int fromIndex, int toIndex) {
|
public static void sort(Object[] a, int fromIndex, int toIndex) {
|
||||||
sort(a, fromIndex, toIndex, new NaturalOrder());
|
sort(a, fromIndex, toIndex, TComparator.NaturalOrder.instance());
|
||||||
}
|
|
||||||
|
|
||||||
private static class NaturalOrder implements TComparator<Object> {
|
|
||||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
|
||||||
@Override public int compare(Object o1, Object o2) {
|
|
||||||
if (o1 != null) {
|
|
||||||
return ((TComparable) o1).compareTo(o2);
|
|
||||||
} else if (o2 != null) {
|
|
||||||
return ((TComparable) o2).compareTo(o1);
|
|
||||||
} else {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <T> void sort(T[] a, int fromIndex, int toIndex, TComparator<? super T> c) {
|
public static <T> void sort(T[] a, int fromIndex, int toIndex, TComparator<? super T> c) {
|
||||||
|
if (c == null) {
|
||||||
|
c = TComparator.NaturalOrder.instance();
|
||||||
|
}
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
T[] subarray = (T[]) new Object[toIndex - fromIndex];
|
T[] subarray = (T[]) new Object[toIndex - fromIndex];
|
||||||
for (int i = fromIndex; i < toIndex; ++i) {
|
for (int i = fromIndex; i < toIndex; ++i) {
|
||||||
|
@ -949,6 +939,9 @@ public class TArrays extends TObject {
|
||||||
if (a.length == 0) {
|
if (a.length == 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (c == null) {
|
||||||
|
c = TComparator.NaturalOrder.instance();
|
||||||
|
}
|
||||||
Object[] first = a;
|
Object[] first = a;
|
||||||
Object[] second = new Object[a.length];
|
Object[] second = new Object[a.length];
|
||||||
int chunkSize = 1;
|
int chunkSize = 1;
|
||||||
|
@ -1225,7 +1218,7 @@ public class TArrays extends TObject {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int binarySearch(Object[] a, int fromIndex, int toIndex, Object key) {
|
public static int binarySearch(Object[] a, int fromIndex, int toIndex, Object key) {
|
||||||
return binarySearch(a, fromIndex, toIndex, key, new NaturalOrder());
|
return binarySearch(a, fromIndex, toIndex, key, TComparator.NaturalOrder.instance());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <T> int binarySearch(T[] a, T key, TComparator<? super T> c) {
|
public static <T> int binarySearch(T[] a, T key, TComparator<? super T> c) {
|
||||||
|
@ -1233,6 +1226,9 @@ public class TArrays extends TObject {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <T> int binarySearch(T[] a, int fromIndex, int toIndex, T key, TComparator<? super T> c) {
|
public static <T> int binarySearch(T[] a, int fromIndex, int toIndex, T key, TComparator<? super T> c) {
|
||||||
|
if (c == null) {
|
||||||
|
c = TComparator.NaturalOrder.instance();
|
||||||
|
}
|
||||||
if (fromIndex > toIndex) {
|
if (fromIndex > toIndex) {
|
||||||
throw new TIllegalArgumentException();
|
throw new TIllegalArgumentException();
|
||||||
}
|
}
|
||||||
|
|
|
@ -216,7 +216,7 @@ public class TCollections extends TObject {
|
||||||
|
|
||||||
public static <T> void sort(TList<T> list, TComparator<? super T> c) {
|
public static <T> void sort(TList<T> list, TComparator<? super T> c) {
|
||||||
if (c == null) {
|
if (c == null) {
|
||||||
c = naturalOrder;
|
c = TComparator.NaturalOrder.instance();
|
||||||
}
|
}
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
T[] array = (T[]) new Object[list.size()];
|
T[] array = (T[]) new Object[list.size()];
|
||||||
|
@ -228,7 +228,7 @@ public class TCollections extends TObject {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <T extends TComparable<? super T>> void sort(TList<T> list) {
|
public static <T extends TComparable<? super T>> void sort(TList<T> list) {
|
||||||
sort(list, naturalOrder);
|
sort(list, TComparator.NaturalOrder.instance());
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
|
@ -244,20 +244,15 @@ public class TCollections extends TObject {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <T> int binarySearch(TList<? extends TComparable<? super T>> list, T key) {
|
public static <T> int binarySearch(TList<? extends TComparable<? super T>> list, T key) {
|
||||||
return binarySearch(list, key, naturalOrder);
|
return binarySearch(list, key, TComparator.NaturalOrder.instance());
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
private static TComparator<Object> naturalOrder = (o1, o2) -> o1 != null
|
|
||||||
? ((TComparable<Object>) o1).compareTo(o2)
|
|
||||||
: -((TComparable<Object>) o2).compareTo(o1);
|
|
||||||
|
|
||||||
public static <T> int binarySearch(TList<? extends T> list, T key, TComparator<? super T> c) {
|
public static <T> int binarySearch(TList<? extends T> list, T key, TComparator<? super T> c) {
|
||||||
if (!(list instanceof TRandomAccess)) {
|
if (!(list instanceof TRandomAccess)) {
|
||||||
list = new TArrayList<>(list);
|
list = new TArrayList<>(list);
|
||||||
}
|
}
|
||||||
if (c == null) {
|
if (c == null) {
|
||||||
c = naturalOrder;
|
c = TComparator.NaturalOrder.instance();
|
||||||
}
|
}
|
||||||
int l = 0;
|
int l = 0;
|
||||||
int u = list.size() - 1;
|
int u = list.size() - 1;
|
||||||
|
@ -339,12 +334,12 @@ public class TCollections extends TObject {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <T extends Object & TComparable<? super T>> T min(TCollection<? extends T> coll) {
|
public static <T extends Object & TComparable<? super T>> T min(TCollection<? extends T> coll) {
|
||||||
return min(coll, naturalOrder);
|
return min(coll, TComparator.NaturalOrder.instance());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <T> T min(TCollection<? extends T> coll, TComparator<? super T> comp) {
|
public static <T> T min(TCollection<? extends T> coll, TComparator<? super T> comp) {
|
||||||
if (comp == null) {
|
if (comp == null) {
|
||||||
comp = naturalOrder;
|
comp = TComparator.NaturalOrder.instance();
|
||||||
}
|
}
|
||||||
TIterator<? extends T> iter = coll.iterator();
|
TIterator<? extends T> iter = coll.iterator();
|
||||||
T min = iter.next();
|
T min = iter.next();
|
||||||
|
@ -358,12 +353,12 @@ public class TCollections extends TObject {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <T extends Object & TComparable<? super T>> T max(TCollection<? extends T> coll) {
|
public static <T extends Object & TComparable<? super T>> T max(TCollection<? extends T> coll) {
|
||||||
return max(coll, naturalOrder);
|
return max(coll, TComparator.NaturalOrder.instance());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <T> T max(TCollection<? extends T> coll, TComparator<? super T> comp) {
|
public static <T> T max(TCollection<? extends T> coll, TComparator<? super T> comp) {
|
||||||
if (comp == null) {
|
if (comp == null) {
|
||||||
comp = naturalOrder;
|
comp = TComparator.NaturalOrder.instance();
|
||||||
}
|
}
|
||||||
TIterator<? extends T> iter = coll.iterator();
|
TIterator<? extends T> iter = coll.iterator();
|
||||||
T max = iter.next();
|
T max = iter.next();
|
||||||
|
@ -557,9 +552,7 @@ public class TCollections extends TObject {
|
||||||
return (TComparator<T>) reverseOrder;
|
return (TComparator<T>) reverseOrder;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static TComparator<Object> reverseOrder = (o1, o2) -> o1 != null
|
private static TComparator<Object> reverseOrder = (o1, o2) -> ((TComparable<Object>) o2).compareTo(o1);
|
||||||
? -((TComparable<Object>) o1).compareTo(o2)
|
|
||||||
: ((TComparable<Object>) o2).compareTo(o1);
|
|
||||||
|
|
||||||
public static <T> TComparator<T> reverseOrder(final TComparator<T> cmp) {
|
public static <T> TComparator<T> reverseOrder(final TComparator<T> cmp) {
|
||||||
return (o1, o2) -> -cmp.compare(o1, o2);
|
return (o1, o2) -> -cmp.compare(o1, o2);
|
||||||
|
|
|
@ -56,7 +56,7 @@ public interface TComparator<T> {
|
||||||
if (r == 0) {
|
if (r == 0) {
|
||||||
U k = keyExtractor.apply(a);
|
U k = keyExtractor.apply(a);
|
||||||
U m = keyExtractor.apply(b);
|
U m = keyExtractor.apply(b);
|
||||||
r = k != null ? k.compareTo(m) : -m.compareTo(k);
|
r = k.compareTo(m);
|
||||||
}
|
}
|
||||||
return r;
|
return r;
|
||||||
};
|
};
|
||||||
|
@ -102,16 +102,31 @@ public interface TComparator<T> {
|
||||||
return (a, b) -> {
|
return (a, b) -> {
|
||||||
U k = keyExtractor.apply(a);
|
U k = keyExtractor.apply(a);
|
||||||
U m = keyExtractor.apply(b);
|
U m = keyExtractor.apply(b);
|
||||||
return k != null ? k.compareTo(m) : -m.compareTo(k);
|
return k.compareTo(m);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class NaturalOrder implements TComparator<Object> {
|
||||||
|
private static final TComparator<Object> INSTANCE = new NaturalOrder();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public int compare(Object o1, Object o2) {
|
||||||
|
return ((Comparable<Object>) o1).compareTo(o2);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
static <T> TComparator<T> instance() {
|
||||||
|
return (TComparator<T>) INSTANCE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static <T extends TComparable<? super T>> TComparator<T> naturalOrder() {
|
static <T extends TComparable<? super T>> TComparator<T> naturalOrder() {
|
||||||
return (o1, o2) -> o1 != null ? o1.compareTo(o2) : o2.compareTo(o1);
|
return NaturalOrder.instance();
|
||||||
}
|
}
|
||||||
|
|
||||||
static <T extends TComparable<? super T>> TComparator<T> reverseOrder() {
|
static <T extends TComparable<? super T>> TComparator<T> reverseOrder() {
|
||||||
return (o1, o2) -> o2 != null ? o2.compareTo(o1) : o1.compareTo(o2);
|
return TCollections.reverseOrder();
|
||||||
}
|
}
|
||||||
|
|
||||||
static <T> TComparator<T> nullsFirst(TComparator<? super T> comparator) {
|
static <T> TComparator<T> nullsFirst(TComparator<? super T> comparator) {
|
||||||
|
|
|
@ -18,6 +18,7 @@ package org.teavm.classlib.java.util;
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
import static org.junit.Assert.fail;
|
import static org.junit.Assert.fail;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Comparator;
|
||||||
import java.util.ConcurrentModificationException;
|
import java.util.ConcurrentModificationException;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
@ -184,4 +185,17 @@ public class ArrayListTest {
|
||||||
assertEquals("[(this Collection), A]", list.toString());
|
assertEquals("[(this Collection), A]", list.toString());
|
||||||
assertEquals("[]", new ArrayList().toString());
|
assertEquals("[]", new ArrayList().toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSort() {
|
||||||
|
int size = 10;
|
||||||
|
List<Integer> list = new ArrayList<>();
|
||||||
|
for (int i = 0; i < size; i++) {
|
||||||
|
list.add(size - 1 - i);
|
||||||
|
}
|
||||||
|
list.sort(Comparator.naturalOrder());
|
||||||
|
for (int i = 0; i < size; i++) {
|
||||||
|
assertEquals(i, list.get(i).intValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,6 +37,7 @@ public class ArraysTest {
|
||||||
assertEquals(Integer.valueOf(5), array[3]);
|
assertEquals(Integer.valueOf(5), array[3]);
|
||||||
assertEquals(Integer.valueOf(6), array[4]);
|
assertEquals(Integer.valueOf(6), array[4]);
|
||||||
assertEquals(Integer.valueOf(7), array[5]);
|
assertEquals(Integer.valueOf(7), array[5]);
|
||||||
|
Arrays.sort(array, null); // NPE check
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -50,6 +51,7 @@ public class ArraysTest {
|
||||||
assertEquals(-3, Arrays.binarySearch(array, 5));
|
assertEquals(-3, Arrays.binarySearch(array, 5));
|
||||||
assertEquals(-8, Arrays.binarySearch(array, 15));
|
assertEquals(-8, Arrays.binarySearch(array, 15));
|
||||||
assertEquals(-9, Arrays.binarySearch(array, 17));
|
assertEquals(-9, Arrays.binarySearch(array, 17));
|
||||||
|
assertEquals(3, Arrays.binarySearch(array, 8, null)); // NPE check
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
|
@ -0,0 +1,92 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2023 ihromant.
|
||||||
|
*
|
||||||
|
* 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 License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.teavm.classlib.java.util;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
import static org.junit.Assert.fail;
|
||||||
|
import java.util.Comparator;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.teavm.junit.TeaVMTestRunner;
|
||||||
|
import org.teavm.junit.WholeClassCompilation;
|
||||||
|
|
||||||
|
@RunWith(TeaVMTestRunner.class)
|
||||||
|
@WholeClassCompilation
|
||||||
|
public class ComparatorTest {
|
||||||
|
@Test
|
||||||
|
public void naturalReverseOrder() {
|
||||||
|
Integer i = 2;
|
||||||
|
Integer j = 3;
|
||||||
|
Comparator<Integer> comp = Comparator.naturalOrder();
|
||||||
|
assertTrue(comp.compare(i, j) < 0);
|
||||||
|
assertEquals(0, comp.compare(i, i));
|
||||||
|
assertTrue(comp.compare(j, i) > 0);
|
||||||
|
Comparator<Integer> rev = Comparator.reverseOrder();
|
||||||
|
assertTrue(rev.compare(i, j) > 0);
|
||||||
|
assertEquals(0, rev.compare(i, i));
|
||||||
|
assertTrue(rev.compare(j, i) < 0);
|
||||||
|
try {
|
||||||
|
comp.compare(i, null);
|
||||||
|
fail("Expected NPE for comparing with null");
|
||||||
|
} catch (NullPointerException e) {
|
||||||
|
// OK
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
comp.compare(null, i);
|
||||||
|
fail("Expected NPE for comparing with null");
|
||||||
|
} catch (NullPointerException e) {
|
||||||
|
// OK
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testComparing() {
|
||||||
|
Point a = new Point(1, 1);
|
||||||
|
Point b = new Point(1, 2);
|
||||||
|
Point c = new Point(2, 1);
|
||||||
|
Point d = new Point(1, null);
|
||||||
|
Comparator<Point> comp = Comparator.comparing(Point::getX).thenComparing(Point::getY);
|
||||||
|
assertTrue(comp.compare(a, c) < 1);
|
||||||
|
assertTrue(comp.compare(a, b) < 1);
|
||||||
|
assertTrue(comp.compare(b, c) < 1);
|
||||||
|
assertEquals(0, comp.compare(a, a));
|
||||||
|
try {
|
||||||
|
comp.compare(a, d);
|
||||||
|
fail("Expected NPE for comparing null fields");
|
||||||
|
} catch (NullPointerException e) {
|
||||||
|
// OK
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class Point {
|
||||||
|
private final Integer x;
|
||||||
|
private final Integer y;
|
||||||
|
|
||||||
|
private Point(Integer x, Integer y) {
|
||||||
|
this.x = x;
|
||||||
|
this.y = y;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getX() {
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getY() {
|
||||||
|
return y;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user