diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ArrayUtilTest.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ArrayUtilTest.java
index 234723a336d..cdab81aa5d8 100644
--- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ArrayUtilTest.java
+++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ArrayUtilTest.java
@@ -229,4 +229,25 @@ public class ArrayUtilTest extends TestCase {
assertSame(result[0], o1);
assertSame(result[1], o2);
}
+
+ public void testRemoveDuplicates() {
+ String[] array = { "1", "2", null, "3", "2", "1", "4", "3" };
+ String[] result = ArrayUtil.removeDuplicates(array);
+ assertEquals(4, result.length);
+ assertEquals("1", result[0]);
+ assertEquals("2", result[1]);
+ assertEquals("3", result[2]);
+ assertEquals("4", result[3]);
+
+ // Test a long array.
+ array = new String[100];
+ for (int i = 0; i < array.length; i++) {
+ array[i] = (i + 1) % 11 == 0 ? null : String.valueOf(i % 17);
+ }
+ result = ArrayUtil.removeDuplicates(array);
+ assertEquals(17, result.length);
+ for (int i = 0; i < result.length - 1; i++) {
+ assertEquals(String.valueOf(i < 10 ? i : i < 16 ? i + 1 : 10), result[i]);
+ }
+ }
}
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/util/ArrayUtil.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/util/ArrayUtil.java
index 8c560e483a1..fb994763f44 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/util/ArrayUtil.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/util/ArrayUtil.java
@@ -18,6 +18,7 @@ import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
+import java.util.LinkedHashSet;
import org.eclipse.core.runtime.Assert;
@@ -257,13 +258,13 @@ public abstract class ArrayUtil {
}
/**
- * Takes contents of the two arrays up to the first null
element and concatenates
+ * Takes contents of the two arrays up to the first {@code null} element and concatenates
* them.
* @param c The type of the element of the returned array if there was not enough free space
* in the destination array.
* @param dest The destination array. The elements of the source array are added to this array
- * if there is enough free space in it. May be null
.
- * @param source The source array. May not be null
.
+ * if there is enough free space in it. May be {@code null}.
+ * @param source The source array. May not be {@code null}.
* @return The concatenated array, which may be the same as the first parameter.
*/
@SuppressWarnings("unchecked")
@@ -300,11 +301,11 @@ public abstract class ArrayUtil {
}
/**
- * Takes contents of the two arrays up to the first null
element and concatenates
+ * Takes contents of the two arrays up to the first {@code null} element and concatenates
* them.
* @param dest The destination array. The elements of the source array are added to this array
- * if there is enough free space in it. May be null
.
- * @param source The source array. May not be null
.
+ * if there is enough free space in it. May be {@code null}.
+ * @param source The source array. May not be {@code null}.
* @return The concatenated array, which may be the same as the first parameter.
* @since 5.2
*/
@@ -362,7 +363,7 @@ public abstract class ArrayUtil {
* @param array the array to search
* @param obj the object to search for
* @return true
if the specified array contains the specified object, or
- * the specified array is null
+ * the specified array is {@code null}
*/
public static boolean contains(T[] array, T obj) {
return indexOf(array, obj) >= 0;
@@ -374,7 +375,7 @@ public abstract class ArrayUtil {
* @param array the array to search
* @param obj the object to search for
* @return the index into the specified array of the specified object, or -1 if the array does
- * not contain the object, or if the array is null
+ * not contain the object, or if the array is {@code null}
*/
public static int indexOf(T[] array, T obj) {
int result = -1;
@@ -391,10 +392,11 @@ public abstract class ArrayUtil {
* Assumes that array contains nulls at the end, only.
* Returns whether the specified array contains the specified object. Comparison is by
* object identity.
+ *
* @param array the array to search
* @param obj the object to search for
* @return true if the specified array contains the specified object, or the specified array is
- * null
+ * {@code null}
*/
public static boolean containsEqual(T[] array, T obj) {
return indexOfEqual(array, obj) != -1;
@@ -404,16 +406,17 @@ public abstract class ArrayUtil {
* Assumes that array contains nulls at the end, only.
* Returns the index into the specified array of the specified object, or -1 if the array does
* not contain the object, or if the array is null. Comparison is by equals().
- * @param comments the array to search
- * @param comment the object to search for
+ *
+ * @param array the array to search
+ * @param obj the object to search for
* @return the index into the specified array of the specified object, or -1 if the array does
- * not contain an equal object, or if the array is null
+ * not contain an equal object, or if the array is {@code null}
*/
- public static int indexOfEqual(T[] comments, T comment) {
+ public static int indexOfEqual(T[] array, T obj) {
int result = -1;
- if (comments != null) {
- for (int i= 0; (i < comments.length) && (comments[i] != null); i++) {
- if (comments[i].equals(comment))
+ if (array != null) {
+ for (int i= 0; (i < array.length) && (array[i] != null); i++) {
+ if (array[i].equals(obj))
return i;
}
}
@@ -566,7 +569,7 @@ public abstract class ArrayUtil {
/**
* Inserts the obj at the beginning of the array, shifting the whole thing one index
* Assumes that array contains nulls at the end, only.
- * array must not be null
.
+ * array must not be {@code null}.
* @since 5.2
*/
public static T[] prepend(T[] array, T obj) {
@@ -660,26 +663,63 @@ public abstract class ArrayUtil {
}
/**
- * Returns a new array that contains all of the elements of the
- * given array except the first one.
+ * Returns a new array that contains all of the elements of the given array except
+ * the first one.
*
+ * @throws NullPointerException if {@code array} is {@code null}
+ * @throws IllegalArgumentException if {@code array} is empty
* @since 5.1
- * @throws NullPointerException if args is null
- * @throws IllegalArgumentException if args.length <= 0
*/
@SuppressWarnings("unchecked")
- public static T[] removeFirst(T[] args) {
- int n = args.length;
+ public static T[] removeFirst(T[] array) {
+ int n = array.length;
if (n <= 0)
throw new IllegalArgumentException();
- T[] newArgs = (T[]) Array.newInstance(args.getClass().getComponentType(), n - 1);
+ T[] newArgs = (T[]) Array.newInstance(array.getClass().getComponentType(), n - 1);
for (int i = 1; i < n; i++) {
- newArgs[i - 1] = args[i];
+ newArgs[i - 1] = array[i];
}
return newArgs;
}
+ /**
+ * Returns a new array that contains elements of the given array except duplicates and
+ * {@code null}s. Duplicates are determined by {@link Object#equals(Object)} method.
+ *
+ * @throws NullPointerException if {@code array} is {@code null}
+ * @since 5.5
+ */
+ @SuppressWarnings("unchecked")
+ public static T[] removeDuplicates(T[] array) {
+ if (array.length >= 16) {
+ LinkedHashSet set = new LinkedHashSet(array.length);
+ for (int i = 0; i < array.length; i++) {
+ T obj = array[i];
+ if (obj != null)
+ set.add(obj);
+ }
+ if (set.size() == array.length)
+ return array;
+ return set.toArray((T[]) Array.newInstance(array.getClass().getComponentType(), set.size()));
+ } else {
+ int k = 0;
+ for (int i = 0; i < array.length; i++) {
+ T obj = array[i];
+ if (obj != null) {
+ array[k++] = obj;
+ for (int j = i + 1; j < array.length; j++) {
+ if (obj.equals(array[j]))
+ array[j] = null;
+ }
+ }
+ }
+ if (k == array.length)
+ return array;
+ return Arrays.copyOf(array, k);
+ }
+ }
+
public static int[] setInt(int[] array, int idx, int val) {
if (array == null) {
array = new int[DEFAULT_LENGTH > idx + 1 ? DEFAULT_LENGTH : idx + 1];