diff --git a/platform/util/src/com/intellij/util/SmartList.java b/platform/util/src/com/intellij/util/SmartList.java index e4d7f108a01c..6ebddcb2679a 100644 --- a/platform/util/src/com/intellij/util/SmartList.java +++ b/platform/util/src/com/intellij/util/SmartList.java @@ -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 extends AbstractList { 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 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 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 extends AbstractList { @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 extends AbstractList { @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 extends AbstractList { @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 extends AbstractList { return a; } } + //noinspection SuspiciousToArrayCall return super.toArray(a); } } - diff --git a/platform/util/src/com/intellij/util/containers/ContainerUtil.java b/platform/util/src/com/intellij/util/containers/ContainerUtil.java index dfc1e773aefa..b086e873777e 100644 --- a/platform/util/src/com/intellij/util/containers/ContainerUtil.java +++ b/platform/util/src/com/intellij/util/containers/ContainerUtil.java @@ -165,6 +165,11 @@ public class ContainerUtil extends ContainerUtilRt { }; } + @NotNull + public static List newSmartList(T... elements) { + return new SmartList(elements); + } + @NotNull public static HashSet newHashSet() { return ContainerUtilRt.newHashSet(); diff --git a/platform/util/testSrc/com/intellij/util/SmartListTest.java b/platform/util/testSrc/com/intellij/util/SmartListTest.java index 9c30d9259697..ec8375a0a753 100644 --- a/platform/util/testSrc/com/intellij/util/SmartListTest.java +++ b/platform/util/testSrc/com/intellij/util/SmartListTest.java @@ -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().size()); } + @Test public void testOneElement() { List l = new SmartList(); - l.add(new Integer(1)); + l.add(1); assertEquals(1, l.size()); assertEquals(1, l.get(0).intValue()); } + @Test public void testTwoElement() { List l = new SmartList(); - 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 l = new SmartList(); - 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 l = new SmartList(); 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 l = new SmartList(); 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 l = new SmartList(new Integer(1)); + SmartList l = new SmartList(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 l = new SmartList(); 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 l = new SmartList(); 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 l = new SmartList(new Integer(0)); + SmartList l = new SmartList(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 l = new SmartList(new Integer(0)); + SmartList l = new SmartList(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 l = new SmartList(Arrays.asList(new Integer[]{new Integer(0), new Integer(1)})); + SmartList l = new SmartList(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()); } - }