Удаление повторяющихся значений из ArrayList
У меня есть один Arraylist из String, и я добавил в него некоторое дублирующее значение. и я просто хочу удалить это дублирующее значение. Так как его удалить.
В этом примере у меня есть одна идея.
List<String> list = new ArrayList<String>();
list.add("Krishna");
list.add("Krishna");
list.add("Kishan");
list.add("Krishn");
list.add("Aryan");
list.add("Harm");
System.out.println("List"+list);
for (int i = 1; i < list.size(); i++) {
String a1 = list.get(i);
String a2 = list.get(i-1);
if (a1.equals(a2)) {
list.remove(a1);
}
}
System.out.println("List after short"+list);
Но есть ли Достаточный способ удалить этот список дубликатов. без использования цикла For?
И я могу это сделать, используя HashSet или каким-либо другим способом, но используя список массивов.
хотел бы предложить ваше предложение. спасибо за ваш ответ заранее.
Ответы
Ответ 1
Вы можете создать LinkedHashSet
из списка. LinkedHashSet
будет содержать каждый элемент только один раз и в том же порядке, что и List
. Затем создайте новый List
из этого LinkedHashSet
. Так эффективно, это однострочный:
list = new ArrayList<String>(new LinkedHashSet<String>(list))
Любой подход, который включает в себя List#contains
или List#remove
, вероятно, уменьшит асимптотическое время работы от O (n) (как в приведенном выше примере) до O (n ^ 2).
EDIT. Для требования, упомянутого в комментарии: Если вы хотите удалить повторяющиеся элементы, но считайте строки равными, игнорируя случай, тогда вы можете сделать что-то вроде этого:
Set<String> toRetain = new TreeSet<String>(String.CASE_INSENSITIVE_ORDER);
toRetain.addAll(list);
Set<String> set = new LinkedHashSet<String>(list);
set.retainAll(new LinkedHashSet<String>(toRetain));
list = new ArrayList<String>(set);
У него будет время работы O (n * logn), которое по-прежнему лучше многих других опций. Обратите внимание, что это выглядит немного сложнее, чем могло бы быть: я предположил, что порядок элементов в списке не может быть изменен. Если порядок элементов в списке не имеет значения, вы можете просто сделать
Set<String> set = new TreeSet<String>(String.CASE_INSENSITIVE_ORDER);
set.addAll(list);
list = new ArrayList<String>(set);
Ответ 2
Если вы хотите использовать только arraylist, то я волнуюсь, что нет лучшего способа, который создаст огромное преимущество в производительности. Но только используя arraylist, который я проверил бы перед добавлением в список, например, следующим
void addToList(String s){
if(!yourList.contains(s))
yourList.add(s);
}
В этом случае подходящим является использование Set.
Ответ 3
Вы можете использовать утилиты Google Guava, как показано ниже.
list = ImmutableSet.copyOf(list).asList();
Это, пожалуй, самый эффективный способ удаления дубликатов из списка и интересно, он сохраняет итерационный порядок.
UPDATE
Но в случае, если вы не хотите включать Guava, дубликаты могут быть удалены, как показано ниже.
ArrayList<String> list = new ArrayList<String>();
list.add("Krishna");
list.add("Krishna");
list.add("Kishan");
list.add("Krishn");
list.add("Aryan");
list.add("Harm");
System.out.println("List"+list);
HashSet hs = new HashSet();
hs.addAll(list);
list.clear();
list.addAll(hs);
Но, конечно, это разрушит порядок итераций элементов в ArrayList.
Шишир
Ответ 4
Java 8 функция потока
Вы можете использовать функцию distinct, как показано выше, чтобы получить отдельные элементы списка,
stringList.stream().distinct();
Из документации
Возвращает поток, состоящий из отдельных элементов (в соответствии с Object.equals(Object)) этого потока.
Другим способом, если вы не хотите использовать метод equals, является функция collect, как это,
stringList.stream()
.collect(Collectors.toCollection(() ->
new TreeSet<String>((p1, p2) -> p1.compareTo(p2))
));
Из документации
Выполняет изменяемую операцию сокращения элементов этого потока с использованием Collector.
Надеюсь, что это поможет.
Ответ 5
List<String> list = new ArrayList<String>();
list.add("Krishna");
list.add("Krishna");
list.add("Kishan");
list.add("Krishn");
list.add("Aryan");
list.add("Harm");
HashSet<String> hs=new HashSet<>(list);
System.out.println("=========With Duplicate Element========");
System.out.println(list);
System.out.println("=========Removed Duplicate Element========");
System.out.println(hs);
Ответ 6
Я не думаю, что list = new ArrayList<String>(new LinkedHashSet<String>(list))
не самый лучший способ, так как мы используем LinkedHashset (мы можем использовать непосредственно LinkedHashset
вместо ArrayList
),
Решение:
import java.util.ArrayList;
public class Arrays extends ArrayList{
@Override
public boolean add(Object e) {
if(!contains(e)){
return super.add(e);
}else{
return false;
}
}
public static void main(String[] args) {
Arrays element=new Arrays();
element.add(1);
element.add(2);
element.add(2);
element.add(3);
System.out.println(element);
}
}
Вывод:
[1, 2, 3]
Здесь я расширяю ArrayList
, поскольку я использую его с некоторыми изменениями, переопределяя метод add
.
Ответ 7
Простая функция для удаления дубликатов из списка
private void removeDuplicates(List<?> list)
{
int count = list.size();
for (int i = 0; i < count; i++)
{
for (int j = i + 1; j < count; j++)
{
if (list.get(i).equals(list.get(j)))
{
list.remove(j--);
count--;
}
}
}
}
Пример:
Вход: [1, 2, 2, 3, 1, 3, 3, 2, 3, 1, 2, 3, 3, 4, 4, 4, 1]
Выход: [1, 2, 3, 4]
Ответ 8
Это будет лучший способ
List<String> list = new ArrayList<String>();
list.add("Krishna");
list.add("Krishna");
list.add("Kishan");
list.add("Krishn");
list.add("Aryan");
list.add("Harm");
Set<String> set=new HashSet<>(list);
Ответ 9
Лучше использовать HastSet
1-a) HashSet содержит набор объектов, но таким образом, что позволяет вам легко и быстро определить, находится ли объект уже в наборе или нет. Он делает это, внутренне управляя массивом и сохраняя объект, используя индекс, который вычисляется из хэш-кода объекта. Взгляните сюда
1-b) HashSet - это неупорядоченная коллекция, содержащая уникальные элементы. Он имеет стандартные операции коллекции Add, Remove, Contains, но поскольку он использует хэш-реализацию, эти операции O (1). (В отличие от List, например O (n) для Contains и Remove.) HashSet также предоставляет стандартные операции набора, такие как объединение, пересечение и симметричная разность. Посмотрите здесь
2) Существуют различные реализации наборов. Некоторые делают операции ввода и поиска сверхбыстрыми элементами хэширования. Однако это означает, что порядок, в котором были добавлены элементы, теряется. Другие реализации сохраняют добавленный заказ за счет более медленного времени работы.
Класс HashSet в С# идет для первого подхода, тем самым не сохраняя порядок элементов. Это намного быстрее обычного списка. Некоторые базовые тесты показали, что HashSet прилично быстрее работает с первичными типами (int, double, bool и т.д.). Это намного быстрее при работе с объектами класса. Таким образом, точка HashSet быстрая.
Единственный улов HashSet - отсутствие доступа по индексам. Для доступа к элементам вы можете либо использовать перечислитель, либо использовать встроенную функцию для преобразования HashSet в список и итерации через это. Посмотрите здесь
Ответ 10
Без цикла Нет! Поскольку ArrayList
индексируется по порядку, а не по ключу, вы не можете найти целевой элемент без повторения всего списка.
Хорошей практикой программирования является выбор правильной структуры данных в соответствии с вашим сценарием. Поэтому, если Set
больше подходит для вашего сценария, обсуждение его реализации с помощью List
и попытка найти самый быстрый способ использования ненадлежащей структуры данных не имеет смысла.
Ответ 11
public static void main(String[] args) {
@SuppressWarnings("serial")
List<Object> lst = new ArrayList<Object>() {
@Override
public boolean add(Object e) {
if(!contains(e))
return super.add(e);
else
return false;
}
};
lst.add("ABC");
lst.add("ABC");
lst.add("ABCD");
lst.add("ABCD");
lst.add("ABCE");
System.out.println(lst);
}
Это лучший способ
Ответ 12
list = list.stream().distinct().collect(Collectors.toList());
Это может быть одно из решений, использующих Java8 Stream API. Надеюсь это поможет.
Ответ 13
Использование java 8:
public static <T> List<T> removeDuplicates(List<T> list) {
return list.stream().collect(Collectors.toSet()).stream().collect(Collectors.toList());
}
Ответ 14
Если вам просто нужно удалить дубликаты, используя только ArrayList, других классов Collection, то: -
//list is the original arraylist containing the duplicates as well
List<String> uniqueList = new ArrayList<String>();
for(int i=0;i<list.size();i++) {
if(!uniqueList.contains(list.get(i)))
uniqueList.add(list.get(i));
}
Надеюсь, это поможет!
Ответ 15
private static void removeDuplicates(List<Integer> list)
{
Collections.sort(list);
int count = list.size();
for (int i = 0; i < count; i++)
{
if(i+1<count && list.get(i)==list.get(i+1)){
list.remove(i);
i--;
count--;
}
}
}
Ответ 16
public List<Contact> removeDuplicates(List<Contact> list) {
// Set set1 = new LinkedHashSet(list);
Set set = new TreeSet(new Comparator() {
@Override
public int compare(Object o1, Object o2) {
if(((Contact)o1).getId().equalsIgnoreCase(((Contact)2).getId()) ) {
return 0;
}
return 1;
}
});
set.addAll(list);
final List newList = new ArrayList(set);
return newList;
}