Возможно, это немного излишне, но мне нравится такая изолированная проблема. :)
Этот код использует временный набор (для проверки уникальности), но удаляет элементы непосредственно внутри исходного списка. Поскольку удаление элемента внутри ArrayList может вызвать огромное количество копирования массива, метод удаления (int) исключается.
public static <T> void removeDuplicates(ArrayList<T> list) {
int size = list.size();
int out = 0;
{
final Set<T> encountered = new HashSet<T>();
for (int in = 0; in < size; in++) {
final T t = list.get(in);
final boolean first = encountered.add(t);
if (first) {
list.set(out++, t);
}
}
}
while (out < size) {
list.remove(--size);
}
}
Пока мы здесь, вот версия для LinkedList (намного приятнее!):
public static <T> void removeDuplicates(LinkedList<T> list) {
final Set<T> encountered = new HashSet<T>();
for (Iterator<T> iter = list.iterator(); iter.hasNext(); ) {
final T t = iter.next();
final boolean first = encountered.add(t);
if (!first) {
iter.remove();
}
}
}
Используйте интерфейс маркера, чтобы представить унифицированное решение для List:
public static <T> void removeDuplicates(List<T> list) {
if (list instanceof RandomAccess) {
// use first version here
} else {
// use other version here
}
}
РЕДАКТИРОВАТЬ: Я думаю, что дженерики действительно не имеют никакой ценности здесь ... Ну, хорошо. :)