From ba95368991e37a1659906685bb00d5cd9b799cf7 Mon Sep 17 00:00:00 2001 From: godotg Date: Sun, 25 Sep 2022 13:09:03 +0800 Subject: [PATCH] =?UTF-8?q?perf[deserialization]:=20=E5=8F=8D=E5=BA=8F?= =?UTF-8?q?=E5=88=97=E5=8C=96=E4=BD=BF=E7=94=A8primitive=20type=20array=20?= =?UTF-8?q?list?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../zfoo/protocol/buffer/ByteBufUtils.java | 57 +--- .../protocol/collection/ArrayBooleanList.java | 313 +++++++++++++++--- .../protocol/collection/ArrayByteList.java | 313 +++++++++++++++--- .../protocol/collection/ArrayDoubleList.java | 313 +++++++++++++++--- .../protocol/collection/ArrayFloatList.java | 313 +++++++++++++++--- .../protocol/collection/ArrayLongList.java | 313 +++++++++++++++--- .../protocol/collection/ArrayShortList.java | 313 +++++++++++++++--- 7 files changed, 1565 insertions(+), 370 deletions(-) diff --git a/protocol/src/main/java/com/zfoo/protocol/buffer/ByteBufUtils.java b/protocol/src/main/java/com/zfoo/protocol/buffer/ByteBufUtils.java index c789d09c..12dc3408 100644 --- a/protocol/src/main/java/com/zfoo/protocol/buffer/ByteBufUtils.java +++ b/protocol/src/main/java/com/zfoo/protocol/buffer/ByteBufUtils.java @@ -417,9 +417,9 @@ public abstract class ByteBufUtils { public static List readPacketList(ByteBuf byteBuf, IProtocolRegistration protocolRegistration) { var length = readInt(byteBuf); - var list = new ArrayList(CollectionUtils.comfortableCapacity(length)); + var list = new ArrayList(CollectionUtils.comfortableLength(length)); for (var i = 0; i < length; i++) { - list.set(i, (IPacket) protocolRegistration.read(byteBuf)); + list.add((IPacket) protocolRegistration.read(byteBuf)); } return list; } @@ -751,12 +751,7 @@ public abstract class ByteBufUtils { } public static List readBooleanList(ByteBuf byteBuf) { - var length = readInt(byteBuf); - var list = new ArrayBooleanList(CollectionUtils.comfortableCapacity(length)); - for (var i = 0; i < length; i++) { - list.set(i, readBoolean(byteBuf)); - } - return list; + return new ArrayBooleanList(readBooleanArray(byteBuf)); } public static void writeBooleanSet(ByteBuf byteBuf, Set set) { @@ -829,12 +824,7 @@ public abstract class ByteBufUtils { } public static List readByteList(ByteBuf byteBuf) { - var length = readInt(byteBuf); - var list = new ArrayByteList(CollectionUtils.comfortableCapacity(length)); - for (var i = 0; i < length; i++) { - list.set(i, readByte(byteBuf)); - } - return list; + return new ArrayByteList(readByteArray(byteBuf)); } public static void writeByteSet(ByteBuf byteBuf, Set set) { @@ -915,12 +905,7 @@ public abstract class ByteBufUtils { } public static List readShortList(ByteBuf byteBuf) { - var length = readInt(byteBuf); - var list = new ArrayShortList(CollectionUtils.comfortableCapacity(length)); - for (var i = 0; i < length; i++) { - list.set(i, readShort(byteBuf)); - } - return list; + return new ArrayShortList(readShortArray(byteBuf)); } public static void writeShortSet(ByteBuf byteBuf, Set set) { @@ -994,12 +979,7 @@ public abstract class ByteBufUtils { } public static List readIntList(ByteBuf byteBuf) { - var length = readInt(byteBuf); - var list = new ArrayIntList(CollectionUtils.comfortableCapacity(length)); - for (var i = 0; i < length; i++) { - list.set(i, readInt(byteBuf)); - } - return list; + return new ArrayIntList(readIntArray(byteBuf)); } public static void writeIntSet(ByteBuf byteBuf, Set set) { @@ -1073,12 +1053,7 @@ public abstract class ByteBufUtils { } public static List readLongList(ByteBuf byteBuf) { - var length = readInt(byteBuf); - var list = new ArrayLongList(CollectionUtils.comfortableCapacity(length)); - for (var i = 0; i < length; i++) { - list.set(i, readLong(byteBuf)); - } - return list; + return new ArrayLongList(readLongArray(byteBuf)); } public static void writeLongSet(ByteBuf byteBuf, Set set) { @@ -1159,12 +1134,7 @@ public abstract class ByteBufUtils { } public static List readFloatList(ByteBuf byteBuf) { - var length = readInt(byteBuf); - var list = new ArrayFloatList(CollectionUtils.comfortableCapacity(length)); - for (var i = 0; i < length; i++) { - list.set(i, readFloat(byteBuf)); - } - return list; + return new ArrayFloatList(readFloatArray(byteBuf)); } public static void writeFloatSet(ByteBuf byteBuf, Set set) { @@ -1245,12 +1215,7 @@ public abstract class ByteBufUtils { } public static List readDoubleList(ByteBuf byteBuf) { - var length = readInt(byteBuf); - var list = new ArrayDoubleList(CollectionUtils.comfortableCapacity(length)); - for (var i = 0; i < length; i++) { - list.set(i, readDouble(byteBuf)); - } - return list; + return new ArrayDoubleList(readDoubleArray(byteBuf)); } public static void writeDoubleSet(ByteBuf byteBuf, Set set) { @@ -1304,9 +1269,9 @@ public abstract class ByteBufUtils { public static List readStringList(ByteBuf byteBuf) { var length = readInt(byteBuf); - var list = new ArrayList(CollectionUtils.comfortableCapacity(length)); + var list = new ArrayList(CollectionUtils.comfortableLength(length)); for (var i = 0; i < length; i++) { - list.set(i, readString(byteBuf)); + list.add(readString(byteBuf)); } return list; } diff --git a/protocol/src/main/java/com/zfoo/protocol/collection/ArrayBooleanList.java b/protocol/src/main/java/com/zfoo/protocol/collection/ArrayBooleanList.java index 3ee0040d..fedb541e 100644 --- a/protocol/src/main/java/com/zfoo/protocol/collection/ArrayBooleanList.java +++ b/protocol/src/main/java/com/zfoo/protocol/collection/ArrayBooleanList.java @@ -12,10 +12,7 @@ package com.zfoo.protocol.collection; -import java.util.Collection; -import java.util.Iterator; -import java.util.List; -import java.util.ListIterator; +import java.util.*; /** * @author godotg @@ -23,86 +20,254 @@ import java.util.ListIterator; */ public class ArrayBooleanList implements List { - private final boolean[] array; + private boolean[] array; + private int size; public ArrayBooleanList(int initialCapacity) { this.array = new boolean[initialCapacity]; } + public ArrayBooleanList(boolean[] array) { + this.array = array; + this.size = array.length; + } + + public void fromList(List list) { + if (CollectionUtils.isEmpty(list)) { + this.size = 0; + return; + } + this.size = list.size(); + this.array = ArrayUtils.booleanToArray(list); + } + + public List toList() { + if (isEmpty()) { + return new ArrayList<>(); + } + return ArrayUtils.toList(toArrayPrimitive()); + } + + public boolean[] toArrayPrimitive() { + return Arrays.copyOf(array, size); + } + + private int getCapacity() { + return array.length - size; + } + + private void ensureCapacity(int capacity) { + var remainCapacity = getCapacity(); + if (capacity > remainCapacity) { + array = Arrays.copyOf(array, size + capacity + 16); + } + } + + private void checkIndexForAdd(int index) { + if (index < 0 || index > size) { + throw new IndexOutOfBoundsException("Index " + index + " is out of range, size = " + size); + } + } + @Override public int size() { - return array.length; + return size; } @Override public boolean isEmpty() { - return ArrayUtils.isEmpty(array); + return size == 0; + } + + @Override + public boolean contains(Object ele) { + return indexOfPrimitive(ArrayUtils.booleanValue((Boolean) ele)) >= 0; } @Override public Boolean get(int index) { - return array[index]; + return getPrimitive(index); } - public boolean getRaw(int index) { + public boolean getPrimitive(int index) { + Objects.checkIndex(index, size); return array[index]; } @Override public Boolean set(int index, Boolean ele) { var old = array[index]; - array[index] = ele; + setPrimitive(index, ArrayUtils.booleanValue(ele)); return old; } - public void set(int index, boolean ele) { + public void setPrimitive(int index, boolean ele) { + Objects.checkIndex(index, size); array[index] = ele; } @Override - public boolean contains(Object ele) { - return ArrayUtils.toList(array).stream().anyMatch(it -> ele.equals(it)); + public boolean add(Boolean ele) { + return addPrimitive(ArrayUtils.booleanValue(ele)); + } + + public boolean addPrimitive(boolean ele) { + ensureCapacity(1); + array[size++] = ele; + return true; + } + + @Override + public void add(int index, Boolean ele) { + addPrimitive(index, ArrayUtils.booleanValue(ele)); + } + + public void addPrimitive(int index, boolean ele) { + checkIndexForAdd(index); + ensureCapacity(1); + System.arraycopy(array, index, array, index + 1, size - index); + array[index] = ele; + size++; + } + + @Override + public boolean addAll(Collection collection) { + if (CollectionUtils.isEmpty(collection)) { + return false; + } + ensureCapacity(collection.size()); + for (var ele : collection) { + add(ele); + } + return true; + } + + @Override + public boolean addAll(int index, Collection collection) { + if (CollectionUtils.isEmpty(collection)) { + return false; + } + checkIndexForAdd(index); + ensureCapacity(collection.size()); + var appendArray = ArrayUtils.booleanToArray(new ArrayList<>(collection)); + var appendLength = appendArray.length; + + var moved = size - index; + if (moved > 0) { + System.arraycopy(array, index, array, index + appendLength, moved); + } + + System.arraycopy(appendArray, 0, array, index, appendLength); + size += appendLength; + return true; + } + + @Override + public boolean remove(Object o) { + var index = indexOf(o); + if (index < 0) { + return false; + } + remove(index); + return true; + } + + @Override + public Boolean remove(int index) { + return removeAt(index); + } + + public boolean removeAt(int index) { + Objects.checkIndex(index, size); + var oldValue = array[index]; + var newSize = size - 1; + if (newSize > index) { + System.arraycopy(array, index + 1, array, index, newSize - index); + } + size--; + return oldValue; + } + + @Override + public boolean removeAll(Collection collection) { + if (CollectionUtils.isEmpty(collection)) { + return false; + } + var list = toList(); + var flag = list.removeAll(collection); + fromList(list); + return flag; + } + + @Override + public boolean retainAll(Collection collection) { + var list = toList(); + var flag = list.retainAll(collection); + fromList(list); + return flag; + } + + @Override + public void clear() { + size = 0; } @Override public Object[] toArray() { - return ArrayUtils.toList(array).toArray(); + return toList().toArray(); } @Override public T[] toArray(T[] arrays) { - ArrayUtils.toList(array).toArray(arrays); - return arrays; + return toList().toArray(arrays); } @Override public boolean containsAll(Collection collection) { - return ArrayUtils.toList(array).containsAll(collection); + return toList().containsAll(collection); + } + + public int indexOfPrimitive(boolean ele) { + for (var i = 0; i < size; i++) { + if (array[i] == ele) { + return i; + } + } + return -1; + } + + public int lastIndexOfPrimitive(boolean ele) { + for (var i = size - 1; i >= 0; i--) { + if (array[i] == ele) { + return i; + } + } + return -1; } @Override public int indexOf(Object ele) { - return ArrayUtils.toList(array).indexOf(ele); + return indexOfPrimitive(ArrayUtils.booleanValue((Boolean) ele)); } @Override public int lastIndexOf(Object ele) { - return ArrayUtils.toList(array).lastIndexOf(ele); + return lastIndexOfPrimitive(ArrayUtils.booleanValue((Boolean) ele)); } @Override public Iterator iterator() { - return ArrayUtils.toList(array).iterator(); + return new FastIterator(); } @Override public ListIterator listIterator() { - return ArrayUtils.toList(array).listIterator(); + return new FastListIterator(0); } @Override public ListIterator listIterator(int index) { - return ArrayUtils.toList(array).listIterator(index); + return new FastListIterator(index); } @Override @@ -111,47 +276,87 @@ public class ArrayBooleanList implements List { } @Override - public boolean add(Boolean e) { - throw new UnsupportedOperationException(); + public String toString() { + var builder = new StringBuilder(); + builder.append('['); + for (var i = 0; i < size; i++) { + builder.append(array[i]); + if (i < size - 1) { + builder.append(", "); + } + } + builder.append(']'); + return builder.toString(); } - @Override - public void add(int index, Boolean element) { - throw new UnsupportedOperationException(); + private class FastIterator implements Iterator { + int cursor; // index of next element to return + int lastCursor = -1; // index of last element returned; -1 if no such + + public boolean hasNext() { + return cursor != size; + } + + @Override + public Boolean next() { + if (cursor >= size) { + throw new NoSuchElementException(); + } + lastCursor = cursor; + return array[cursor++]; + } + + @Override + public void remove() { + if (lastCursor < 0) { + throw new IllegalStateException(); + } + removeAt(lastCursor); + cursor = lastCursor; + lastCursor = -1; + } } - @Override - public boolean addAll(Collection collection) { - throw new UnsupportedOperationException(); - } + private class FastListIterator extends FastIterator implements ListIterator { + FastListIterator(int index) { + super(); + cursor = index; + } - @Override - public boolean addAll(int index, Collection collection) { - throw new UnsupportedOperationException(); - } + public boolean hasPrevious() { + return cursor != 0; + } - @Override - public boolean remove(Object o) { - throw new UnsupportedOperationException(); - } + public int nextIndex() { + return cursor; + } - @Override - public Boolean remove(int index) { - throw new UnsupportedOperationException(); - } + public int previousIndex() { + return cursor - 1; + } - @Override - public boolean removeAll(Collection collection) { - throw new UnsupportedOperationException(); - } + @Override + public Boolean previous() { + if (cursor <= 0) { + throw new NoSuchElementException(); + } + cursor--; + lastCursor = cursor; + return array[cursor]; + } - @Override - public boolean retainAll(Collection collection) { - throw new UnsupportedOperationException(); - } + @Override + public void set(Boolean e) { + if (lastCursor < 0) { + throw new IllegalStateException(); + } + setPrimitive(lastCursor, ArrayUtils.booleanValue(e)); + } - @Override - public void clear() { - throw new UnsupportedOperationException(); + @Override + public void add(Boolean e) { + addPrimitive(cursor++, e); + lastCursor = -1; + } } } diff --git a/protocol/src/main/java/com/zfoo/protocol/collection/ArrayByteList.java b/protocol/src/main/java/com/zfoo/protocol/collection/ArrayByteList.java index 2e76a89f..8614181d 100644 --- a/protocol/src/main/java/com/zfoo/protocol/collection/ArrayByteList.java +++ b/protocol/src/main/java/com/zfoo/protocol/collection/ArrayByteList.java @@ -12,10 +12,7 @@ package com.zfoo.protocol.collection; -import java.util.Collection; -import java.util.Iterator; -import java.util.List; -import java.util.ListIterator; +import java.util.*; /** * @author godotg @@ -23,86 +20,254 @@ import java.util.ListIterator; */ public class ArrayByteList implements List { - private final byte[] array; + private byte[] array; + private int size; public ArrayByteList(int initialCapacity) { this.array = new byte[initialCapacity]; } + public ArrayByteList(byte[] array) { + this.array = array; + this.size = array.length; + } + + public void fromList(List list) { + if (CollectionUtils.isEmpty(list)) { + this.size = 0; + return; + } + this.size = list.size(); + this.array = ArrayUtils.byteToArray(list); + } + + public List toList() { + if (isEmpty()) { + return new ArrayList<>(); + } + return ArrayUtils.toList(toArrayPrimitive()); + } + + public byte[] toArrayPrimitive() { + return Arrays.copyOf(array, size); + } + + private int getCapacity() { + return array.length - size; + } + + private void ensureCapacity(int capacity) { + var remainCapacity = getCapacity(); + if (capacity > remainCapacity) { + array = Arrays.copyOf(array, size + capacity + 16); + } + } + + private void checkIndexForAdd(int index) { + if (index < 0 || index > size) { + throw new IndexOutOfBoundsException("Index " + index + " is out of range, size = " + size); + } + } + @Override public int size() { - return array.length; + return size; } @Override public boolean isEmpty() { - return ArrayUtils.isEmpty(array); + return size == 0; + } + + @Override + public boolean contains(Object ele) { + return indexOfPrimitive(ArrayUtils.byteValue((Byte) ele)) >= 0; } @Override public Byte get(int index) { - return array[index]; + return getPrimitive(index); } - public byte getRaw(int index) { + public byte getPrimitive(int index) { + Objects.checkIndex(index, size); return array[index]; } @Override public Byte set(int index, Byte ele) { var old = array[index]; - array[index] = ele; + setPrimitive(index, ArrayUtils.byteValue(ele)); return old; } - public void set(int index, byte ele) { + public void setPrimitive(int index, byte ele) { + Objects.checkIndex(index, size); array[index] = ele; } @Override - public boolean contains(Object ele) { - return ArrayUtils.toList(array).stream().anyMatch(it -> ele.equals(it)); + public boolean add(Byte ele) { + return addPrimitive(ArrayUtils.byteValue(ele)); + } + + public boolean addPrimitive(byte ele) { + ensureCapacity(1); + array[size++] = ele; + return true; + } + + @Override + public void add(int index, Byte ele) { + addPrimitive(index, ArrayUtils.byteValue(ele)); + } + + public void addPrimitive(int index, byte ele) { + checkIndexForAdd(index); + ensureCapacity(1); + System.arraycopy(array, index, array, index + 1, size - index); + array[index] = ele; + size++; + } + + @Override + public boolean addAll(Collection collection) { + if (CollectionUtils.isEmpty(collection)) { + return false; + } + ensureCapacity(collection.size()); + for (var ele : collection) { + add(ele); + } + return true; + } + + @Override + public boolean addAll(int index, Collection collection) { + if (CollectionUtils.isEmpty(collection)) { + return false; + } + checkIndexForAdd(index); + ensureCapacity(collection.size()); + var appendArray = ArrayUtils.byteToArray(new ArrayList<>(collection)); + var appendLength = appendArray.length; + + var moved = size - index; + if (moved > 0) { + System.arraycopy(array, index, array, index + appendLength, moved); + } + + System.arraycopy(appendArray, 0, array, index, appendLength); + size += appendLength; + return true; + } + + @Override + public boolean remove(Object o) { + var index = indexOf(o); + if (index < 0) { + return false; + } + remove(index); + return true; + } + + @Override + public Byte remove(int index) { + return removeAt(index); + } + + public byte removeAt(int index) { + Objects.checkIndex(index, size); + var oldValue = array[index]; + var newSize = size - 1; + if (newSize > index) { + System.arraycopy(array, index + 1, array, index, newSize - index); + } + size--; + return oldValue; + } + + @Override + public boolean removeAll(Collection collection) { + if (CollectionUtils.isEmpty(collection)) { + return false; + } + var list = toList(); + var flag = list.removeAll(collection); + fromList(list); + return flag; + } + + @Override + public boolean retainAll(Collection collection) { + var list = toList(); + var flag = list.retainAll(collection); + fromList(list); + return flag; + } + + @Override + public void clear() { + size = 0; } @Override public Object[] toArray() { - return ArrayUtils.toList(array).toArray(); + return toList().toArray(); } @Override public T[] toArray(T[] arrays) { - ArrayUtils.toList(array).toArray(arrays); - return arrays; + return toList().toArray(arrays); } @Override public boolean containsAll(Collection collection) { - return ArrayUtils.toList(array).containsAll(collection); + return toList().containsAll(collection); + } + + public int indexOfPrimitive(byte ele) { + for (var i = 0; i < size; i++) { + if (array[i] == ele) { + return i; + } + } + return -1; + } + + public int lastIndexOfPrimitive(byte ele) { + for (var i = size - 1; i >= 0; i--) { + if (array[i] == ele) { + return i; + } + } + return -1; } @Override public int indexOf(Object ele) { - return ArrayUtils.toList(array).indexOf(ele); + return indexOfPrimitive(ArrayUtils.byteValue((Byte) ele)); } @Override public int lastIndexOf(Object ele) { - return ArrayUtils.toList(array).lastIndexOf(ele); + return lastIndexOfPrimitive(ArrayUtils.byteValue((Byte) ele)); } @Override public Iterator iterator() { - return ArrayUtils.toList(array).iterator(); + return new FastIterator(); } @Override public ListIterator listIterator() { - return ArrayUtils.toList(array).listIterator(); + return new FastListIterator(0); } @Override public ListIterator listIterator(int index) { - return ArrayUtils.toList(array).listIterator(index); + return new FastListIterator(index); } @Override @@ -111,47 +276,87 @@ public class ArrayByteList implements List { } @Override - public boolean add(Byte e) { - throw new UnsupportedOperationException(); + public String toString() { + var builder = new StringBuilder(); + builder.append('['); + for (var i = 0; i < size; i++) { + builder.append(array[i]); + if (i < size - 1) { + builder.append(", "); + } + } + builder.append(']'); + return builder.toString(); } - @Override - public void add(int index, Byte element) { - throw new UnsupportedOperationException(); + private class FastIterator implements Iterator { + int cursor; // index of next element to return + int lastCursor = -1; // index of last element returned; -1 if no such + + public boolean hasNext() { + return cursor != size; + } + + @Override + public Byte next() { + if (cursor >= size) { + throw new NoSuchElementException(); + } + lastCursor = cursor; + return array[cursor++]; + } + + @Override + public void remove() { + if (lastCursor < 0) { + throw new IllegalStateException(); + } + removeAt(lastCursor); + cursor = lastCursor; + lastCursor = -1; + } } - @Override - public boolean addAll(Collection collection) { - throw new UnsupportedOperationException(); - } + private class FastListIterator extends FastIterator implements ListIterator { + FastListIterator(int index) { + super(); + cursor = index; + } - @Override - public boolean addAll(int index, Collection collection) { - throw new UnsupportedOperationException(); - } + public boolean hasPrevious() { + return cursor != 0; + } - @Override - public boolean remove(Object o) { - throw new UnsupportedOperationException(); - } + public int nextIndex() { + return cursor; + } - @Override - public Byte remove(int index) { - throw new UnsupportedOperationException(); - } + public int previousIndex() { + return cursor - 1; + } - @Override - public boolean removeAll(Collection collection) { - throw new UnsupportedOperationException(); - } + @Override + public Byte previous() { + if (cursor <= 0) { + throw new NoSuchElementException(); + } + cursor--; + lastCursor = cursor; + return array[cursor]; + } - @Override - public boolean retainAll(Collection collection) { - throw new UnsupportedOperationException(); - } + @Override + public void set(Byte e) { + if (lastCursor < 0) { + throw new IllegalStateException(); + } + setPrimitive(lastCursor, ArrayUtils.byteValue(e)); + } - @Override - public void clear() { - throw new UnsupportedOperationException(); + @Override + public void add(Byte e) { + addPrimitive(cursor++, e); + lastCursor = -1; + } } } diff --git a/protocol/src/main/java/com/zfoo/protocol/collection/ArrayDoubleList.java b/protocol/src/main/java/com/zfoo/protocol/collection/ArrayDoubleList.java index e3ca5a12..1cdd76bf 100644 --- a/protocol/src/main/java/com/zfoo/protocol/collection/ArrayDoubleList.java +++ b/protocol/src/main/java/com/zfoo/protocol/collection/ArrayDoubleList.java @@ -12,10 +12,7 @@ package com.zfoo.protocol.collection; -import java.util.Collection; -import java.util.Iterator; -import java.util.List; -import java.util.ListIterator; +import java.util.*; /** * @author godotg @@ -23,86 +20,254 @@ import java.util.ListIterator; */ public class ArrayDoubleList implements List { - private final double[] array; + private double[] array; + private int size; public ArrayDoubleList(int initialCapacity) { this.array = new double[initialCapacity]; } + public ArrayDoubleList(double[] array) { + this.array = array; + this.size = array.length; + } + + public void fromList(List list) { + if (CollectionUtils.isEmpty(list)) { + this.size = 0; + return; + } + this.size = list.size(); + this.array = ArrayUtils.doubleToArray(list); + } + + public List toList() { + if (isEmpty()) { + return new ArrayList<>(); + } + return ArrayUtils.toList(toArrayPrimitive()); + } + + public double[] toArrayPrimitive() { + return Arrays.copyOf(array, size); + } + + private int getCapacity() { + return array.length - size; + } + + private void ensureCapacity(int capacity) { + var remainCapacity = getCapacity(); + if (capacity > remainCapacity) { + array = Arrays.copyOf(array, size + capacity + 16); + } + } + + private void checkIndexForAdd(int index) { + if (index < 0 || index > size) { + throw new IndexOutOfBoundsException("Index " + index + " is out of range, size = " + size); + } + } + @Override public int size() { - return array.length; + return size; } @Override public boolean isEmpty() { - return ArrayUtils.isEmpty(array); + return size == 0; + } + + @Override + public boolean contains(Object ele) { + return indexOfPrimitive(ArrayUtils.doubleValue((Double) ele)) >= 0; } @Override public Double get(int index) { - return array[index]; + return getPrimitive(index); } - public double getRaw(int index) { + public double getPrimitive(int index) { + Objects.checkIndex(index, size); return array[index]; } @Override public Double set(int index, Double ele) { var old = array[index]; - array[index] = ele; + setPrimitive(index, ArrayUtils.doubleValue(ele)); return old; } - public void set(int index, double ele) { + public void setPrimitive(int index, double ele) { + Objects.checkIndex(index, size); array[index] = ele; } @Override - public boolean contains(Object ele) { - return ArrayUtils.toList(array).stream().anyMatch(it -> ele.equals(it)); + public boolean add(Double ele) { + return addPrimitive(ArrayUtils.doubleValue(ele)); + } + + public boolean addPrimitive(double ele) { + ensureCapacity(1); + array[size++] = ele; + return true; + } + + @Override + public void add(int index, Double ele) { + addPrimitive(index, ArrayUtils.doubleValue(ele)); + } + + public void addPrimitive(int index, double ele) { + checkIndexForAdd(index); + ensureCapacity(1); + System.arraycopy(array, index, array, index + 1, size - index); + array[index] = ele; + size++; + } + + @Override + public boolean addAll(Collection collection) { + if (CollectionUtils.isEmpty(collection)) { + return false; + } + ensureCapacity(collection.size()); + for (var ele : collection) { + add(ele); + } + return true; + } + + @Override + public boolean addAll(int index, Collection collection) { + if (CollectionUtils.isEmpty(collection)) { + return false; + } + checkIndexForAdd(index); + ensureCapacity(collection.size()); + var appendArray = ArrayUtils.doubleToArray(new ArrayList<>(collection)); + var appendLength = appendArray.length; + + var moved = size - index; + if (moved > 0) { + System.arraycopy(array, index, array, index + appendLength, moved); + } + + System.arraycopy(appendArray, 0, array, index, appendLength); + size += appendLength; + return true; + } + + @Override + public boolean remove(Object o) { + var index = indexOf(o); + if (index < 0) { + return false; + } + remove(index); + return true; + } + + @Override + public Double remove(int index) { + return removeAt(index); + } + + public double removeAt(int index) { + Objects.checkIndex(index, size); + var oldValue = array[index]; + var newSize = size - 1; + if (newSize > index) { + System.arraycopy(array, index + 1, array, index, newSize - index); + } + size--; + return oldValue; + } + + @Override + public boolean removeAll(Collection collection) { + if (CollectionUtils.isEmpty(collection)) { + return false; + } + var list = toList(); + var flag = list.removeAll(collection); + fromList(list); + return flag; + } + + @Override + public boolean retainAll(Collection collection) { + var list = toList(); + var flag = list.retainAll(collection); + fromList(list); + return flag; + } + + @Override + public void clear() { + size = 0; } @Override public Object[] toArray() { - return ArrayUtils.toList(array).toArray(); + return toList().toArray(); } @Override public T[] toArray(T[] arrays) { - ArrayUtils.toList(array).toArray(arrays); - return arrays; + return toList().toArray(arrays); } @Override public boolean containsAll(Collection collection) { - return ArrayUtils.toList(array).containsAll(collection); + return toList().containsAll(collection); + } + + public int indexOfPrimitive(double ele) { + for (var i = 0; i < size; i++) { + if (array[i] == ele) { + return i; + } + } + return -1; + } + + public int lastIndexOfPrimitive(double ele) { + for (var i = size - 1; i >= 0; i--) { + if (array[i] == ele) { + return i; + } + } + return -1; } @Override public int indexOf(Object ele) { - return ArrayUtils.toList(array).indexOf(ele); + return indexOfPrimitive(ArrayUtils.doubleValue((Double) ele)); } @Override public int lastIndexOf(Object ele) { - return ArrayUtils.toList(array).lastIndexOf(ele); + return lastIndexOfPrimitive(ArrayUtils.doubleValue((Double) ele)); } @Override public Iterator iterator() { - return ArrayUtils.toList(array).iterator(); + return new FastIterator(); } @Override public ListIterator listIterator() { - return ArrayUtils.toList(array).listIterator(); + return new FastListIterator(0); } @Override public ListIterator listIterator(int index) { - return ArrayUtils.toList(array).listIterator(index); + return new FastListIterator(index); } @Override @@ -111,47 +276,87 @@ public class ArrayDoubleList implements List { } @Override - public boolean add(Double e) { - throw new UnsupportedOperationException(); + public String toString() { + var builder = new StringBuilder(); + builder.append('['); + for (var i = 0; i < size; i++) { + builder.append(array[i]); + if (i < size - 1) { + builder.append(", "); + } + } + builder.append(']'); + return builder.toString(); } - @Override - public void add(int index, Double element) { - throw new UnsupportedOperationException(); + private class FastIterator implements Iterator { + int cursor; // index of next element to return + int lastCursor = -1; // index of last element returned; -1 if no such + + public boolean hasNext() { + return cursor != size; + } + + @Override + public Double next() { + if (cursor >= size) { + throw new NoSuchElementException(); + } + lastCursor = cursor; + return array[cursor++]; + } + + @Override + public void remove() { + if (lastCursor < 0) { + throw new IllegalStateException(); + } + removeAt(lastCursor); + cursor = lastCursor; + lastCursor = -1; + } } - @Override - public boolean addAll(Collection collection) { - throw new UnsupportedOperationException(); - } + private class FastListIterator extends FastIterator implements ListIterator { + FastListIterator(int index) { + super(); + cursor = index; + } - @Override - public boolean addAll(int index, Collection collection) { - throw new UnsupportedOperationException(); - } + public boolean hasPrevious() { + return cursor != 0; + } - @Override - public boolean remove(Object o) { - throw new UnsupportedOperationException(); - } + public int nextIndex() { + return cursor; + } - @Override - public Double remove(int index) { - throw new UnsupportedOperationException(); - } + public int previousIndex() { + return cursor - 1; + } - @Override - public boolean removeAll(Collection collection) { - throw new UnsupportedOperationException(); - } + @Override + public Double previous() { + if (cursor <= 0) { + throw new NoSuchElementException(); + } + cursor--; + lastCursor = cursor; + return array[cursor]; + } - @Override - public boolean retainAll(Collection collection) { - throw new UnsupportedOperationException(); - } + @Override + public void set(Double e) { + if (lastCursor < 0) { + throw new IllegalStateException(); + } + setPrimitive(lastCursor, ArrayUtils.doubleValue(e)); + } - @Override - public void clear() { - throw new UnsupportedOperationException(); + @Override + public void add(Double e) { + addPrimitive(cursor++, e); + lastCursor = -1; + } } } diff --git a/protocol/src/main/java/com/zfoo/protocol/collection/ArrayFloatList.java b/protocol/src/main/java/com/zfoo/protocol/collection/ArrayFloatList.java index acec6e02..c3c3aef2 100644 --- a/protocol/src/main/java/com/zfoo/protocol/collection/ArrayFloatList.java +++ b/protocol/src/main/java/com/zfoo/protocol/collection/ArrayFloatList.java @@ -12,10 +12,7 @@ package com.zfoo.protocol.collection; -import java.util.Collection; -import java.util.Iterator; -import java.util.List; -import java.util.ListIterator; +import java.util.*; /** * @author godotg @@ -23,86 +20,254 @@ import java.util.ListIterator; */ public class ArrayFloatList implements List { - private final float[] array; + private float[] array; + private int size; public ArrayFloatList(int initialCapacity) { this.array = new float[initialCapacity]; } + public ArrayFloatList(float[] array) { + this.array = array; + this.size = array.length; + } + + public void fromList(List list) { + if (CollectionUtils.isEmpty(list)) { + this.size = 0; + return; + } + this.size = list.size(); + this.array = ArrayUtils.floatToArray(list); + } + + public List toList() { + if (isEmpty()) { + return new ArrayList<>(); + } + return ArrayUtils.toList(toArrayPrimitive()); + } + + public float[] toArrayPrimitive() { + return Arrays.copyOf(array, size); + } + + private int getCapacity() { + return array.length - size; + } + + private void ensureCapacity(int capacity) { + var remainCapacity = getCapacity(); + if (capacity > remainCapacity) { + array = Arrays.copyOf(array, size + capacity + 16); + } + } + + private void checkIndexForAdd(int index) { + if (index < 0 || index > size) { + throw new IndexOutOfBoundsException("Index " + index + " is out of range, size = " + size); + } + } + @Override public int size() { - return array.length; + return size; } @Override public boolean isEmpty() { - return ArrayUtils.isEmpty(array); + return size == 0; + } + + @Override + public boolean contains(Object ele) { + return indexOfPrimitive(ArrayUtils.floatValue((Float) ele)) >= 0; } @Override public Float get(int index) { - return array[index]; + return getPrimitive(index); } - public float getRaw(int index) { + public float getPrimitive(int index) { + Objects.checkIndex(index, size); return array[index]; } @Override public Float set(int index, Float ele) { var old = array[index]; - array[index] = ele; + setPrimitive(index, ArrayUtils.floatValue(ele)); return old; } - public void set(int index, float ele) { + public void setPrimitive(int index, float ele) { + Objects.checkIndex(index, size); array[index] = ele; } @Override - public boolean contains(Object ele) { - return ArrayUtils.toList(array).stream().anyMatch(it -> ele.equals(it)); + public boolean add(Float ele) { + return addPrimitive(ArrayUtils.floatValue(ele)); + } + + public boolean addPrimitive(float ele) { + ensureCapacity(1); + array[size++] = ele; + return true; + } + + @Override + public void add(int index, Float ele) { + addPrimitive(index, ArrayUtils.floatValue(ele)); + } + + public void addPrimitive(int index, float ele) { + checkIndexForAdd(index); + ensureCapacity(1); + System.arraycopy(array, index, array, index + 1, size - index); + array[index] = ele; + size++; + } + + @Override + public boolean addAll(Collection collection) { + if (CollectionUtils.isEmpty(collection)) { + return false; + } + ensureCapacity(collection.size()); + for (var ele : collection) { + add(ele); + } + return true; + } + + @Override + public boolean addAll(int index, Collection collection) { + if (CollectionUtils.isEmpty(collection)) { + return false; + } + checkIndexForAdd(index); + ensureCapacity(collection.size()); + var appendArray = ArrayUtils.floatToArray(new ArrayList<>(collection)); + var appendLength = appendArray.length; + + var moved = size - index; + if (moved > 0) { + System.arraycopy(array, index, array, index + appendLength, moved); + } + + System.arraycopy(appendArray, 0, array, index, appendLength); + size += appendLength; + return true; + } + + @Override + public boolean remove(Object o) { + var index = indexOf(o); + if (index < 0) { + return false; + } + remove(index); + return true; + } + + @Override + public Float remove(int index) { + return removeAt(index); + } + + public float removeAt(int index) { + Objects.checkIndex(index, size); + var oldValue = array[index]; + var newSize = size - 1; + if (newSize > index) { + System.arraycopy(array, index + 1, array, index, newSize - index); + } + size--; + return oldValue; + } + + @Override + public boolean removeAll(Collection collection) { + if (CollectionUtils.isEmpty(collection)) { + return false; + } + var list = toList(); + var flag = list.removeAll(collection); + fromList(list); + return flag; + } + + @Override + public boolean retainAll(Collection collection) { + var list = toList(); + var flag = list.retainAll(collection); + fromList(list); + return flag; + } + + @Override + public void clear() { + size = 0; } @Override public Object[] toArray() { - return ArrayUtils.toList(array).toArray(); + return toList().toArray(); } @Override public T[] toArray(T[] arrays) { - ArrayUtils.toList(array).toArray(arrays); - return arrays; + return toList().toArray(arrays); } @Override public boolean containsAll(Collection collection) { - return ArrayUtils.toList(array).containsAll(collection); + return toList().containsAll(collection); + } + + public int indexOfPrimitive(float ele) { + for (var i = 0; i < size; i++) { + if (array[i] == ele) { + return i; + } + } + return -1; + } + + public int lastIndexOfPrimitive(float ele) { + for (var i = size - 1; i >= 0; i--) { + if (array[i] == ele) { + return i; + } + } + return -1; } @Override public int indexOf(Object ele) { - return ArrayUtils.toList(array).indexOf(ele); + return indexOfPrimitive(ArrayUtils.floatValue((Float) ele)); } @Override public int lastIndexOf(Object ele) { - return ArrayUtils.toList(array).lastIndexOf(ele); + return lastIndexOfPrimitive(ArrayUtils.floatValue((Float) ele)); } @Override public Iterator iterator() { - return ArrayUtils.toList(array).iterator(); + return new FastIterator(); } @Override public ListIterator listIterator() { - return ArrayUtils.toList(array).listIterator(); + return new FastListIterator(0); } @Override public ListIterator listIterator(int index) { - return ArrayUtils.toList(array).listIterator(index); + return new FastListIterator(index); } @Override @@ -111,47 +276,87 @@ public class ArrayFloatList implements List { } @Override - public boolean add(Float e) { - throw new UnsupportedOperationException(); + public String toString() { + var builder = new StringBuilder(); + builder.append('['); + for (var i = 0; i < size; i++) { + builder.append(array[i]); + if (i < size - 1) { + builder.append(", "); + } + } + builder.append(']'); + return builder.toString(); } - @Override - public void add(int index, Float element) { - throw new UnsupportedOperationException(); + private class FastIterator implements Iterator { + int cursor; // index of next element to return + int lastCursor = -1; // index of last element returned; -1 if no such + + public boolean hasNext() { + return cursor != size; + } + + @Override + public Float next() { + if (cursor >= size) { + throw new NoSuchElementException(); + } + lastCursor = cursor; + return array[cursor++]; + } + + @Override + public void remove() { + if (lastCursor < 0) { + throw new IllegalStateException(); + } + removeAt(lastCursor); + cursor = lastCursor; + lastCursor = -1; + } } - @Override - public boolean addAll(Collection collection) { - throw new UnsupportedOperationException(); - } + private class FastListIterator extends FastIterator implements ListIterator { + FastListIterator(int index) { + super(); + cursor = index; + } - @Override - public boolean addAll(int index, Collection collection) { - throw new UnsupportedOperationException(); - } + public boolean hasPrevious() { + return cursor != 0; + } - @Override - public boolean remove(Object o) { - throw new UnsupportedOperationException(); - } + public int nextIndex() { + return cursor; + } - @Override - public Float remove(int index) { - throw new UnsupportedOperationException(); - } + public int previousIndex() { + return cursor - 1; + } - @Override - public boolean removeAll(Collection collection) { - throw new UnsupportedOperationException(); - } + @Override + public Float previous() { + if (cursor <= 0) { + throw new NoSuchElementException(); + } + cursor--; + lastCursor = cursor; + return array[cursor]; + } - @Override - public boolean retainAll(Collection collection) { - throw new UnsupportedOperationException(); - } + @Override + public void set(Float e) { + if (lastCursor < 0) { + throw new IllegalStateException(); + } + setPrimitive(lastCursor, ArrayUtils.floatValue(e)); + } - @Override - public void clear() { - throw new UnsupportedOperationException(); + @Override + public void add(Float e) { + addPrimitive(cursor++, e); + lastCursor = -1; + } } } diff --git a/protocol/src/main/java/com/zfoo/protocol/collection/ArrayLongList.java b/protocol/src/main/java/com/zfoo/protocol/collection/ArrayLongList.java index 803592b5..ff34d044 100644 --- a/protocol/src/main/java/com/zfoo/protocol/collection/ArrayLongList.java +++ b/protocol/src/main/java/com/zfoo/protocol/collection/ArrayLongList.java @@ -12,10 +12,7 @@ package com.zfoo.protocol.collection; -import java.util.Collection; -import java.util.Iterator; -import java.util.List; -import java.util.ListIterator; +import java.util.*; /** * @author godotg @@ -23,86 +20,254 @@ import java.util.ListIterator; */ public class ArrayLongList implements List { - private final long[] array; + private long[] array; + private int size; public ArrayLongList(int initialCapacity) { this.array = new long[initialCapacity]; } + public ArrayLongList(long[] array) { + this.array = array; + this.size = array.length; + } + + public void fromList(List list) { + if (CollectionUtils.isEmpty(list)) { + this.size = 0; + return; + } + this.size = list.size(); + this.array = ArrayUtils.longToArray(list); + } + + public List toList() { + if (isEmpty()) { + return new ArrayList<>(); + } + return ArrayUtils.toList(toArrayPrimitive()); + } + + public long[] toArrayPrimitive() { + return Arrays.copyOf(array, size); + } + + private int getCapacity() { + return array.length - size; + } + + private void ensureCapacity(int capacity) { + var remainCapacity = getCapacity(); + if (capacity > remainCapacity) { + array = Arrays.copyOf(array, size + capacity + 16); + } + } + + private void checkIndexForAdd(int index) { + if (index < 0 || index > size) { + throw new IndexOutOfBoundsException("Index " + index + " is out of range, size = " + size); + } + } + @Override public int size() { - return array.length; + return size; } @Override public boolean isEmpty() { - return ArrayUtils.isEmpty(array); + return size == 0; + } + + @Override + public boolean contains(Object ele) { + return indexOfPrimitive(ArrayUtils.longValue((Long) ele)) >= 0; } @Override public Long get(int index) { - return array[index]; + return getPrimitive(index); } - public long getRaw(int index) { + public long getPrimitive(int index) { + Objects.checkIndex(index, size); return array[index]; } @Override public Long set(int index, Long ele) { var old = array[index]; - array[index] = ele; + setPrimitive(index, ArrayUtils.longValue(ele)); return old; } - public void set(int index, long ele) { + public void setPrimitive(int index, long ele) { + Objects.checkIndex(index, size); array[index] = ele; } @Override - public boolean contains(Object ele) { - return ArrayUtils.toList(array).stream().anyMatch(it -> ele.equals(it)); + public boolean add(Long ele) { + return addPrimitive(ArrayUtils.longValue(ele)); + } + + public boolean addPrimitive(long ele) { + ensureCapacity(1); + array[size++] = ele; + return true; + } + + @Override + public void add(int index, Long ele) { + addPrimitive(index, ArrayUtils.longValue(ele)); + } + + public void addPrimitive(int index, long ele) { + checkIndexForAdd(index); + ensureCapacity(1); + System.arraycopy(array, index, array, index + 1, size - index); + array[index] = ele; + size++; + } + + @Override + public boolean addAll(Collection collection) { + if (CollectionUtils.isEmpty(collection)) { + return false; + } + ensureCapacity(collection.size()); + for (var ele : collection) { + add(ele); + } + return true; + } + + @Override + public boolean addAll(int index, Collection collection) { + if (CollectionUtils.isEmpty(collection)) { + return false; + } + checkIndexForAdd(index); + ensureCapacity(collection.size()); + var appendArray = ArrayUtils.longToArray(new ArrayList<>(collection)); + var appendLength = appendArray.length; + + var moved = size - index; + if (moved > 0) { + System.arraycopy(array, index, array, index + appendLength, moved); + } + + System.arraycopy(appendArray, 0, array, index, appendLength); + size += appendLength; + return true; + } + + @Override + public boolean remove(Object o) { + var index = indexOf(o); + if (index < 0) { + return false; + } + remove(index); + return true; + } + + @Override + public Long remove(int index) { + return removeAt(index); + } + + public long removeAt(int index) { + Objects.checkIndex(index, size); + var oldValue = array[index]; + var newSize = size - 1; + if (newSize > index) { + System.arraycopy(array, index + 1, array, index, newSize - index); + } + size--; + return oldValue; + } + + @Override + public boolean removeAll(Collection collection) { + if (CollectionUtils.isEmpty(collection)) { + return false; + } + var list = toList(); + var flag = list.removeAll(collection); + fromList(list); + return flag; + } + + @Override + public boolean retainAll(Collection collection) { + var list = toList(); + var flag = list.retainAll(collection); + fromList(list); + return flag; + } + + @Override + public void clear() { + size = 0; } @Override public Object[] toArray() { - return ArrayUtils.toList(array).toArray(); + return toList().toArray(); } @Override public T[] toArray(T[] arrays) { - ArrayUtils.toList(array).toArray(arrays); - return arrays; + return toList().toArray(arrays); } @Override public boolean containsAll(Collection collection) { - return ArrayUtils.toList(array).containsAll(collection); + return toList().containsAll(collection); + } + + public int indexOfPrimitive(long ele) { + for (var i = 0; i < size; i++) { + if (array[i] == ele) { + return i; + } + } + return -1; + } + + public int lastIndexOfPrimitive(long ele) { + for (var i = size - 1; i >= 0; i--) { + if (array[i] == ele) { + return i; + } + } + return -1; } @Override public int indexOf(Object ele) { - return ArrayUtils.toList(array).indexOf(ele); + return indexOfPrimitive(ArrayUtils.longValue((Long) ele)); } @Override public int lastIndexOf(Object ele) { - return ArrayUtils.toList(array).lastIndexOf(ele); + return lastIndexOfPrimitive(ArrayUtils.longValue((Long) ele)); } @Override public Iterator iterator() { - return ArrayUtils.toList(array).iterator(); + return new FastIterator(); } @Override public ListIterator listIterator() { - return ArrayUtils.toList(array).listIterator(); + return new FastListIterator(0); } @Override public ListIterator listIterator(int index) { - return ArrayUtils.toList(array).listIterator(index); + return new FastListIterator(index); } @Override @@ -111,47 +276,87 @@ public class ArrayLongList implements List { } @Override - public boolean add(Long e) { - throw new UnsupportedOperationException(); + public String toString() { + var builder = new StringBuilder(); + builder.append('['); + for (var i = 0; i < size; i++) { + builder.append(array[i]); + if (i < size - 1) { + builder.append(", "); + } + } + builder.append(']'); + return builder.toString(); } - @Override - public void add(int index, Long element) { - throw new UnsupportedOperationException(); + private class FastIterator implements Iterator { + int cursor; // index of next element to return + int lastCursor = -1; // index of last element returned; -1 if no such + + public boolean hasNext() { + return cursor != size; + } + + @Override + public Long next() { + if (cursor >= size) { + throw new NoSuchElementException(); + } + lastCursor = cursor; + return array[cursor++]; + } + + @Override + public void remove() { + if (lastCursor < 0) { + throw new IllegalStateException(); + } + removeAt(lastCursor); + cursor = lastCursor; + lastCursor = -1; + } } - @Override - public boolean addAll(Collection collection) { - throw new UnsupportedOperationException(); - } + private class FastListIterator extends FastIterator implements ListIterator { + FastListIterator(int index) { + super(); + cursor = index; + } - @Override - public boolean addAll(int index, Collection collection) { - throw new UnsupportedOperationException(); - } + public boolean hasPrevious() { + return cursor != 0; + } - @Override - public boolean remove(Object o) { - throw new UnsupportedOperationException(); - } + public int nextIndex() { + return cursor; + } - @Override - public Long remove(int index) { - throw new UnsupportedOperationException(); - } + public int previousIndex() { + return cursor - 1; + } - @Override - public boolean removeAll(Collection collection) { - throw new UnsupportedOperationException(); - } + @Override + public Long previous() { + if (cursor <= 0) { + throw new NoSuchElementException(); + } + cursor--; + lastCursor = cursor; + return array[cursor]; + } - @Override - public boolean retainAll(Collection collection) { - throw new UnsupportedOperationException(); - } + @Override + public void set(Long e) { + if (lastCursor < 0) { + throw new IllegalStateException(); + } + setPrimitive(lastCursor, ArrayUtils.longValue(e)); + } - @Override - public void clear() { - throw new UnsupportedOperationException(); + @Override + public void add(Long e) { + addPrimitive(cursor++, e); + lastCursor = -1; + } } } diff --git a/protocol/src/main/java/com/zfoo/protocol/collection/ArrayShortList.java b/protocol/src/main/java/com/zfoo/protocol/collection/ArrayShortList.java index 981fd274..d81ad341 100644 --- a/protocol/src/main/java/com/zfoo/protocol/collection/ArrayShortList.java +++ b/protocol/src/main/java/com/zfoo/protocol/collection/ArrayShortList.java @@ -12,10 +12,7 @@ package com.zfoo.protocol.collection; -import java.util.Collection; -import java.util.Iterator; -import java.util.List; -import java.util.ListIterator; +import java.util.*; /** * @author godotg @@ -23,86 +20,254 @@ import java.util.ListIterator; */ public class ArrayShortList implements List { - private final short[] array; + private short[] array; + private int size; public ArrayShortList(int initialCapacity) { this.array = new short[initialCapacity]; } + public ArrayShortList(short[] array) { + this.array = array; + this.size = array.length; + } + + public void fromList(List list) { + if (CollectionUtils.isEmpty(list)) { + this.size = 0; + return; + } + this.size = list.size(); + this.array = ArrayUtils.shortToArray(list); + } + + public List toList() { + if (isEmpty()) { + return new ArrayList<>(); + } + return ArrayUtils.toList(toArrayPrimitive()); + } + + public short[] toArrayPrimitive() { + return Arrays.copyOf(array, size); + } + + private int getCapacity() { + return array.length - size; + } + + private void ensureCapacity(int capacity) { + var remainCapacity = getCapacity(); + if (capacity > remainCapacity) { + array = Arrays.copyOf(array, size + capacity + 16); + } + } + + private void checkIndexForAdd(int index) { + if (index < 0 || index > size) { + throw new IndexOutOfBoundsException("Index " + index + " is out of range, size = " + size); + } + } + @Override public int size() { - return array.length; + return size; } @Override public boolean isEmpty() { - return ArrayUtils.isEmpty(array); + return size == 0; + } + + @Override + public boolean contains(Object ele) { + return indexOfPrimitive(ArrayUtils.shortValue((Short) ele)) >= 0; } @Override public Short get(int index) { - return array[index]; + return getPrimitive(index); } - public short getRaw(int index) { + public short getPrimitive(int index) { + Objects.checkIndex(index, size); return array[index]; } @Override public Short set(int index, Short ele) { var old = array[index]; - array[index] = ele; + setPrimitive(index, ArrayUtils.shortValue(ele)); return old; } - public void set(int index, short ele) { + public void setPrimitive(int index, short ele) { + Objects.checkIndex(index, size); array[index] = ele; } @Override - public boolean contains(Object ele) { - return ArrayUtils.toList(array).stream().anyMatch(it -> ele.equals(it)); + public boolean add(Short ele) { + return addPrimitive(ArrayUtils.shortValue(ele)); + } + + public boolean addPrimitive(short ele) { + ensureCapacity(1); + array[size++] = ele; + return true; + } + + @Override + public void add(int index, Short ele) { + addPrimitive(index, ArrayUtils.shortValue(ele)); + } + + public void addPrimitive(int index, short ele) { + checkIndexForAdd(index); + ensureCapacity(1); + System.arraycopy(array, index, array, index + 1, size - index); + array[index] = ele; + size++; + } + + @Override + public boolean addAll(Collection collection) { + if (CollectionUtils.isEmpty(collection)) { + return false; + } + ensureCapacity(collection.size()); + for (var ele : collection) { + add(ele); + } + return true; + } + + @Override + public boolean addAll(int index, Collection collection) { + if (CollectionUtils.isEmpty(collection)) { + return false; + } + checkIndexForAdd(index); + ensureCapacity(collection.size()); + var appendArray = ArrayUtils.shortToArray(new ArrayList<>(collection)); + var appendLength = appendArray.length; + + var moved = size - index; + if (moved > 0) { + System.arraycopy(array, index, array, index + appendLength, moved); + } + + System.arraycopy(appendArray, 0, array, index, appendLength); + size += appendLength; + return true; + } + + @Override + public boolean remove(Object o) { + var index = indexOf(o); + if (index < 0) { + return false; + } + remove(index); + return true; + } + + @Override + public Short remove(int index) { + return removeAt(index); + } + + public short removeAt(int index) { + Objects.checkIndex(index, size); + var oldValue = array[index]; + var newSize = size - 1; + if (newSize > index) { + System.arraycopy(array, index + 1, array, index, newSize - index); + } + size--; + return oldValue; + } + + @Override + public boolean removeAll(Collection collection) { + if (CollectionUtils.isEmpty(collection)) { + return false; + } + var list = toList(); + var flag = list.removeAll(collection); + fromList(list); + return flag; + } + + @Override + public boolean retainAll(Collection collection) { + var list = toList(); + var flag = list.retainAll(collection); + fromList(list); + return flag; + } + + @Override + public void clear() { + size = 0; } @Override public Object[] toArray() { - return ArrayUtils.toList(array).toArray(); + return toList().toArray(); } @Override public T[] toArray(T[] arrays) { - ArrayUtils.toList(array).toArray(arrays); - return arrays; + return toList().toArray(arrays); } @Override public boolean containsAll(Collection collection) { - return ArrayUtils.toList(array).containsAll(collection); + return toList().containsAll(collection); + } + + public int indexOfPrimitive(short ele) { + for (var i = 0; i < size; i++) { + if (array[i] == ele) { + return i; + } + } + return -1; + } + + public int lastIndexOfPrimitive(short ele) { + for (var i = size - 1; i >= 0; i--) { + if (array[i] == ele) { + return i; + } + } + return -1; } @Override public int indexOf(Object ele) { - return ArrayUtils.toList(array).indexOf(ele); + return indexOfPrimitive(ArrayUtils.shortValue((Short) ele)); } @Override public int lastIndexOf(Object ele) { - return ArrayUtils.toList(array).lastIndexOf(ele); + return lastIndexOfPrimitive(ArrayUtils.shortValue((Short) ele)); } @Override public Iterator iterator() { - return ArrayUtils.toList(array).iterator(); + return new FastIterator(); } @Override public ListIterator listIterator() { - return ArrayUtils.toList(array).listIterator(); + return new FastListIterator(0); } @Override public ListIterator listIterator(int index) { - return ArrayUtils.toList(array).listIterator(index); + return new FastListIterator(index); } @Override @@ -111,47 +276,87 @@ public class ArrayShortList implements List { } @Override - public boolean add(Short e) { - throw new UnsupportedOperationException(); + public String toString() { + var builder = new StringBuilder(); + builder.append('['); + for (var i = 0; i < size; i++) { + builder.append(array[i]); + if (i < size - 1) { + builder.append(", "); + } + } + builder.append(']'); + return builder.toString(); } - @Override - public void add(int index, Short element) { - throw new UnsupportedOperationException(); + private class FastIterator implements Iterator { + int cursor; // index of next element to return + int lastCursor = -1; // index of last element returned; -1 if no such + + public boolean hasNext() { + return cursor != size; + } + + @Override + public Short next() { + if (cursor >= size) { + throw new NoSuchElementException(); + } + lastCursor = cursor; + return array[cursor++]; + } + + @Override + public void remove() { + if (lastCursor < 0) { + throw new IllegalStateException(); + } + removeAt(lastCursor); + cursor = lastCursor; + lastCursor = -1; + } } - @Override - public boolean addAll(Collection collection) { - throw new UnsupportedOperationException(); - } + private class FastListIterator extends FastIterator implements ListIterator { + FastListIterator(int index) { + super(); + cursor = index; + } - @Override - public boolean addAll(int index, Collection collection) { - throw new UnsupportedOperationException(); - } + public boolean hasPrevious() { + return cursor != 0; + } - @Override - public boolean remove(Object o) { - throw new UnsupportedOperationException(); - } + public int nextIndex() { + return cursor; + } - @Override - public Short remove(int index) { - throw new UnsupportedOperationException(); - } + public int previousIndex() { + return cursor - 1; + } - @Override - public boolean removeAll(Collection collection) { - throw new UnsupportedOperationException(); - } + @Override + public Short previous() { + if (cursor <= 0) { + throw new NoSuchElementException(); + } + cursor--; + lastCursor = cursor; + return array[cursor]; + } - @Override - public boolean retainAll(Collection collection) { - throw new UnsupportedOperationException(); - } + @Override + public void set(Short e) { + if (lastCursor < 0) { + throw new IllegalStateException(); + } + setPrimitive(lastCursor, ArrayUtils.shortValue(e)); + } - @Override - public void clear() { - throw new UnsupportedOperationException(); + @Override + public void add(Short e) { + addPrimitive(cursor++, e); + lastCursor = -1; + } } }