mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 08:14:09 -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) {
|
||||
int sz = size();
|
||||
for (int i = 0; i < sz; ++i) {
|
||||
Object e = get(i);
|
||||
if (o == null ? e == null : o.equals(e)) {
|
||||
if (TObjects.equals(o, get(i))) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
@ -111,8 +110,7 @@ public abstract class TAbstractList<E> extends TAbstractCollection<E> implements
|
|||
public int lastIndexOf(Object o) {
|
||||
int sz = size();
|
||||
for (int i = sz - 1; i >= 0; --i) {
|
||||
Object e = get(i);
|
||||
if (o == null ? e == null : o.equals(e)) {
|
||||
if (TObjects.equals(o, get(i))) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -129,6 +129,7 @@ public class TArrayList<E> extends TAbstractList<E> implements TCloneable, TSeri
|
|||
public void clear() {
|
||||
Arrays.fill(array, 0, size, null);
|
||||
size = 0;
|
||||
++modCount;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -210,4 +211,10 @@ public class TArrayList<E> extends TAbstractList<E> implements TCloneable, TSeri
|
|||
buffer.append(array[length] == this ? "(this Collection)" : array[length]);
|
||||
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) {
|
||||
sort(a, new NaturalOrder());
|
||||
sort(a, TComparator.NaturalOrder.instance());
|
||||
}
|
||||
|
||||
public static void sort(Object[] a, int fromIndex, int toIndex) {
|
||||
sort(a, fromIndex, toIndex, new NaturalOrder());
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
sort(a, fromIndex, toIndex, TComparator.NaturalOrder.instance());
|
||||
}
|
||||
|
||||
public static <T> void sort(T[] a, int fromIndex, int toIndex, TComparator<? super T> c) {
|
||||
if (c == null) {
|
||||
c = TComparator.NaturalOrder.instance();
|
||||
}
|
||||
@SuppressWarnings("unchecked")
|
||||
T[] subarray = (T[]) new Object[toIndex - fromIndex];
|
||||
for (int i = fromIndex; i < toIndex; ++i) {
|
||||
|
@ -949,6 +939,9 @@ public class TArrays extends TObject {
|
|||
if (a.length == 0) {
|
||||
return;
|
||||
}
|
||||
if (c == null) {
|
||||
c = TComparator.NaturalOrder.instance();
|
||||
}
|
||||
Object[] first = a;
|
||||
Object[] second = new Object[a.length];
|
||||
int chunkSize = 1;
|
||||
|
@ -1225,7 +1218,7 @@ public class TArrays extends TObject {
|
|||
}
|
||||
|
||||
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) {
|
||||
|
@ -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) {
|
||||
if (c == null) {
|
||||
c = TComparator.NaturalOrder.instance();
|
||||
}
|
||||
if (fromIndex > toIndex) {
|
||||
throw new TIllegalArgumentException();
|
||||
}
|
||||
|
|
|
@ -216,7 +216,7 @@ public class TCollections extends TObject {
|
|||
|
||||
public static <T> void sort(TList<T> list, TComparator<? super T> c) {
|
||||
if (c == null) {
|
||||
c = naturalOrder;
|
||||
c = TComparator.NaturalOrder.instance();
|
||||
}
|
||||
@SuppressWarnings("unchecked")
|
||||
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) {
|
||||
sort(list, naturalOrder);
|
||||
sort(list, TComparator.NaturalOrder.instance());
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
|
@ -244,20 +244,15 @@ public class TCollections extends TObject {
|
|||
}
|
||||
|
||||
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) {
|
||||
if (!(list instanceof TRandomAccess)) {
|
||||
list = new TArrayList<>(list);
|
||||
}
|
||||
if (c == null) {
|
||||
c = naturalOrder;
|
||||
c = TComparator.NaturalOrder.instance();
|
||||
}
|
||||
int l = 0;
|
||||
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) {
|
||||
return min(coll, naturalOrder);
|
||||
return min(coll, TComparator.NaturalOrder.instance());
|
||||
}
|
||||
|
||||
public static <T> T min(TCollection<? extends T> coll, TComparator<? super T> comp) {
|
||||
if (comp == null) {
|
||||
comp = naturalOrder;
|
||||
comp = TComparator.NaturalOrder.instance();
|
||||
}
|
||||
TIterator<? extends T> iter = coll.iterator();
|
||||
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) {
|
||||
return max(coll, naturalOrder);
|
||||
return max(coll, TComparator.NaturalOrder.instance());
|
||||
}
|
||||
|
||||
public static <T> T max(TCollection<? extends T> coll, TComparator<? super T> comp) {
|
||||
if (comp == null) {
|
||||
comp = naturalOrder;
|
||||
comp = TComparator.NaturalOrder.instance();
|
||||
}
|
||||
TIterator<? extends T> iter = coll.iterator();
|
||||
T max = iter.next();
|
||||
|
@ -557,9 +552,7 @@ public class TCollections extends TObject {
|
|||
return (TComparator<T>) reverseOrder;
|
||||
}
|
||||
|
||||
private static TComparator<Object> reverseOrder = (o1, o2) -> o1 != null
|
||||
? -((TComparable<Object>) o1).compareTo(o2)
|
||||
: ((TComparable<Object>) o2).compareTo(o1);
|
||||
private static TComparator<Object> reverseOrder = (o1, o2) -> ((TComparable<Object>) o2).compareTo(o1);
|
||||
|
||||
public static <T> TComparator<T> reverseOrder(final TComparator<T> cmp) {
|
||||
return (o1, o2) -> -cmp.compare(o1, o2);
|
||||
|
|
|
@ -56,7 +56,7 @@ public interface TComparator<T> {
|
|||
if (r == 0) {
|
||||
U k = keyExtractor.apply(a);
|
||||
U m = keyExtractor.apply(b);
|
||||
r = k != null ? k.compareTo(m) : -m.compareTo(k);
|
||||
r = k.compareTo(m);
|
||||
}
|
||||
return r;
|
||||
};
|
||||
|
@ -102,16 +102,31 @@ public interface TComparator<T> {
|
|||
return (a, b) -> {
|
||||
U k = keyExtractor.apply(a);
|
||||
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() {
|
||||
return (o1, o2) -> o1 != null ? o1.compareTo(o2) : o2.compareTo(o1);
|
||||
return NaturalOrder.instance();
|
||||
}
|
||||
|
||||
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) {
|
||||
|
|
|
@ -18,6 +18,7 @@ package org.teavm.classlib.java.util;
|
|||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.fail;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.ConcurrentModificationException;
|
||||
import java.util.List;
|
||||
import org.junit.Test;
|
||||
|
@ -184,4 +185,17 @@ public class ArrayListTest {
|
|||
assertEquals("[(this Collection), A]", list.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(6), array[4]);
|
||||
assertEquals(Integer.valueOf(7), array[5]);
|
||||
Arrays.sort(array, null); // NPE check
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -50,6 +51,7 @@ public class ArraysTest {
|
|||
assertEquals(-3, Arrays.binarySearch(array, 5));
|
||||
assertEquals(-8, Arrays.binarySearch(array, 15));
|
||||
assertEquals(-9, Arrays.binarySearch(array, 17));
|
||||
assertEquals(3, Arrays.binarySearch(array, 8, null)); // NPE check
|
||||
}
|
||||
|
||||
@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