Я хотел получить list
уникальных элементов от list
с дублирующимися элементами, и порядок элементов, присутствующих в списке, должен быть сохранен.
Чтобы достичь этого, я мог бы написатьалгоритм типа:
private ArrayList<T> getUnique(ArrayList<T> list)
{
// maintain a hashmap of numbers and a uniqueList to be returned(ArrayList<T>)
// Add element in result list and the hashmap if the element isn't already present in the hashmap, else just add in the hashmap
HashMap<T, Boolean> map = new HashMap<>();
ArrayList<T> uniqueList = new ArrayList<>();
for (T t: list)
{
if (map.get(t) == null)
{
// t wasn't present so, adding them in map as well as in the list
map.put(t, true);
uniqueList.add(t);
}
}
return uniqueList;
}
Этот алгоритм займет O(n)
времени с O(n)
дополнительным пробелом (для HashMap).
Или просто, я мог бы использовать следующий синтаксис:
Set<T> set = new LinkedHashSet<>(list);
Приведенный выше синтаксис в Java используется для получения set
уникальных элементов из list
с порядком вхождения элементов, аналогичным list
.Затем преобразуйте этот набор в список.(ArrayList<T> uniqueList = new ArrayList<>(set);
)
Я предполагаю, что сложность времени здесь также O(n)
.Я хотел знать, какой алгоритм Java использует для этого.
Я вижу, что класс называется LinkedHashSet, поэтому я подумал, что для этого они могут использовать некоторые LinkedList
концепции, поэтому я посмотрел исходный код,и нашел эти вещи:
- В
LinkedHashSet.java
конструктор выглядит так:
143: public LinkedHashSet(Collection<? extends T> c)
144: {
145: super(c);
146: }
здесь является источником.
Итак, я посмотрел на конструктор родительского класса, т.е.
HashSet
, я нашел:
public HashSet(Collection<? extends E> c) {
map = new HashMap<>(Math.max((int) (c.size()/.75f) + 1, 16));
addAll(c);
}
Затем я искал метод
addAll
, я нашел его в классе
AbstractCollection
(который является прародителем класса
HashSet
), определение функции:
public boolean addAll(Collection<? extends E> c) {
boolean modified = false;
for (E e : c)
if (add(e))
modified = true;
return modified;
}
Это вызов add
, который выглядит так:
public boolean add(E e) {
throw new UnsupportedOperationException();
}
здесь .
Я не мог этого понять.Какой алгоритм они используют для этой задачи?