Simplified SmartList creation

This commit is contained in:
Roman Shevchenko
2012-12-13 19:58:20 +01:00
parent f0f1ca179d
commit 094fd514ee
3 changed files with 87 additions and 40 deletions
@@ -21,29 +21,46 @@ import org.jetbrains.annotations.NotNull;
import java.util.*;
/**
* The List which is optimised for the sizes of 0 and 1.
* In which cases it would not allocate array at all.
* A List which is optimised for the sizes of 0 and 1,
* in which cases it would not allocate array at all.
*/
@SuppressWarnings({"unchecked"})
public class SmartList<E> extends AbstractList<E> {
private int mySize = 0;
private Object myElem = null; // null if mySize==0, (E)elem if mySize==1, Object[] if mySize>=2
public SmartList() {
public SmartList() { }
public SmartList(E element) {
add(element);
}
public SmartList(E elem) {
add(elem);
public SmartList(@NotNull Collection<? extends E> elements) {
int size = elements.size();
if (size == 1) {
E element = elements instanceof List ? (E)((List)elements).get(0) : elements.iterator().next();
add(element);
}
else if (size > 0) {
mySize = size;
myElem = elements.toArray(new Object[size]);
}
}
public SmartList(@NotNull Collection<? extends E> c) {
addAll(c);
public SmartList(E... elements) {
if (elements.length == 1) {
add(elements[0]);
}
else if (elements.length > 0) {
mySize = elements.length;
myElem = Arrays.copyOf(elements, mySize);
}
}
@Override
public E get(int index) {
if (index < 0 || index >= mySize) {
throw new IndexOutOfBoundsException("index= " + index + ". Must be index >= 0 && index < " + mySize);
throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + mySize);
}
if (mySize == 1) {
return (E)myElem;
@@ -87,7 +104,7 @@ public class SmartList<E> extends AbstractList<E> {
@Override
public void add(int index, E e) {
if (index < 0 || index > mySize) {
throw new IndexOutOfBoundsException("index= " + index + ". Must be index >= 0 && index < " + mySize);
throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + mySize);
}
if (mySize == 0) {
@@ -132,8 +149,9 @@ public class SmartList<E> extends AbstractList<E> {
@Override
public E set(final int index, final E element) {
if (index < 0 || index >= mySize) {
throw new IndexOutOfBoundsException("index= " + index + ". Must be index > 0 && index < " + mySize);
throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + mySize);
}
final E oldValue;
if (mySize == 1) {
oldValue = (E)myElem;
@@ -150,8 +168,9 @@ public class SmartList<E> extends AbstractList<E> {
@Override
public E remove(final int index) {
if (index < 0 || index >= mySize) {
throw new IndexOutOfBoundsException("index= " + index + ". Must be index >= 0 && index < " + mySize);
throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + mySize);
}
final E oldValue;
if (mySize == 1) {
oldValue = (E)myElem;
@@ -244,7 +263,7 @@ public class SmartList<E> extends AbstractList<E> {
return a;
}
}
//noinspection SuspiciousToArrayCall
return super.toArray(a);
}
}
@@ -165,6 +165,11 @@ public class ContainerUtil extends ContainerUtilRt {
};
}
@NotNull
public static <T> List<T> newSmartList(T... elements) {
return new SmartList<T>(elements);
}
@NotNull
public static <T> HashSet<T> newHashSet() {
return ContainerUtilRt.newHashSet();
@@ -16,53 +16,66 @@
package com.intellij.util;
import com.intellij.util.containers.EmptyIterator;
import junit.framework.TestCase;
import org.junit.Test;
import java.util.*;
import java.util.ConcurrentModificationException;
import java.util.Iterator;
import java.util.List;
import static org.junit.Assert.*;
/**
* @author max
*/
public class SmartListTest extends TestCase {
public class SmartListTest {
@Test
public void testEmpty() {
assertEquals(0, new SmartList<Integer>().size());
}
@Test
public void testOneElement() {
List<Integer> l = new SmartList<Integer>();
l.add(new Integer(1));
l.add(1);
assertEquals(1, l.size());
assertEquals(1, l.get(0).intValue());
}
@Test
public void testTwoElement() {
List<Integer> l = new SmartList<Integer>();
l.add(new Integer(1));
l.add(new Integer(2));
l.add(1);
l.add(2);
assertEquals(2, l.size());
assertEquals(1, l.get(0).intValue());
assertEquals(2, l.get(1).intValue());
}
@Test
public void testThreeElement() {
List<Integer> l = new SmartList<Integer>();
l.add(new Integer(1));
l.add(new Integer(2));
l.add(new Integer(3));
l.add(1);
l.add(2);
l.add(3);
assertEquals(3, l.size());
assertEquals(1, l.get(0).intValue());
assertEquals(2, l.get(1).intValue());
assertEquals(3, l.get(2).intValue());
}
@Test
public void testFourElement() {
SmartList<Integer> l = new SmartList<Integer>();
int modCount = 0;
assertEquals(modCount, l.getModificationCount());
l.add(new Integer(1)); assertEquals(++modCount, l.getModificationCount());
l.add(new Integer(2)); assertEquals(++modCount, l.getModificationCount());
l.add(new Integer(3)); assertEquals(++modCount, l.getModificationCount());
l.add(new Integer(4)); assertEquals(++modCount, l.getModificationCount());
l.add(1);
assertEquals(++modCount, l.getModificationCount());
l.add(2);
assertEquals(++modCount, l.getModificationCount());
l.add(3);
assertEquals(++modCount, l.getModificationCount());
l.add(4);
assertEquals(++modCount, l.getModificationCount());
assertEquals(4, l.size());
assertEquals(1, l.get(0).intValue());
assertEquals(2, l.get(1).intValue());
@@ -132,79 +145,89 @@ public class SmartListTest extends TestCase {
assertTrue("ConcurrentModificationException must be thrown", thrown);
}
@Test
public void testAddIndexedNegativeIndex() {
SmartList<Integer> l = new SmartList<Integer>();
try {
l.add(-1, new Integer(1));
l.add(-1, 1);
}
catch (Exception e) {
return;
}
fail("IndexOutOfBoundsException must be thrown");
fail("IndexOutOfBoundsException must be thrown, " + l);
}
@Test
public void testAddIndexedWrongIndex() {
SmartList<Integer> l = new SmartList<Integer>(new Integer(1));
SmartList<Integer> l = new SmartList<Integer>(1);
try {
l.add(3, new Integer(1));
l.add(3, 1);
}
catch (Exception e) {
return;
}
fail("IndexOutOfBoundsException must be thrown");
fail("IndexOutOfBoundsException must be thrown, " + l);
}
@Test
public void testAddIndexedEmptyWrongIndex() {
SmartList<Integer> l = new SmartList<Integer>();
try {
l.add(1, new Integer(1));
l.add(1, 1);
}
catch (Exception e) {
return;
}
fail("IndexOutOfBoundsException must be thrown");
fail("IndexOutOfBoundsException must be thrown, " + l);
}
@Test
public void testAddIndexedEmpty() {
SmartList<Integer> l = new SmartList<Integer>();
int modCount = 0;
l.add(0, new Integer(1)); assertEquals(++modCount, l.getModificationCount());
l.add(0, 1);
assertEquals(++modCount, l.getModificationCount());
assertEquals(1, l.size());
assertEquals(1, l.get(0).intValue());
}
@Test
public void testAddIndexedOneElement() {
SmartList<Integer> l = new SmartList<Integer>(new Integer(0));
SmartList<Integer> l = new SmartList<Integer>(0);
assertEquals(1, l.size());
int modCount = l.getModificationCount();
l.add(0, new Integer(42)); assertEquals(++modCount, l.getModificationCount());
l.add(0, 42);
assertEquals(++modCount, l.getModificationCount());
assertEquals(2, l.size());
assertEquals(42, l.get(0).intValue());
assertEquals(0, l.get(1).intValue());
}
@Test
public void testAddIndexedOverOneElement() {
SmartList<Integer> l = new SmartList<Integer>(new Integer(0));
SmartList<Integer> l = new SmartList<Integer>(0);
assertEquals(1, l.size());
int modCount = l.getModificationCount();
l.add(1, new Integer(42)); assertEquals(++modCount, l.getModificationCount());
l.add(1, 42);
assertEquals(++modCount, l.getModificationCount());
assertEquals(2, l.size());
assertEquals(0, l.get(0).intValue());
assertEquals(42, l.get(1).intValue());
}
@Test
public void testAddIndexedOverTwoElements() {
SmartList<Integer> l = new SmartList<Integer>(Arrays.asList(new Integer[]{new Integer(0), new Integer(1)}));
SmartList<Integer> l = new SmartList<Integer>(0, 1);
assertEquals(2, l.size());
int modCount = l.getModificationCount();
l.add(1, new Integer(42)); assertEquals(++modCount, l.getModificationCount());
l.add(1, 42);
assertEquals(++modCount, l.getModificationCount());
assertEquals(3, l.size());
assertEquals(0, l.get(0).intValue());
assertEquals(42, l.get(1).intValue());
assertEquals(1, l.get(2).intValue());
}
}