У меня есть ArrayList<String>
, и я хочу удалить из него повторяющиеся строки. Как я могу это сделать?
Если вам не нужны дубликаты в Коллекции
, то следует подумать, почему вы используете Коллекцию
, допускающую дубликаты. Самый простой способ удалить повторяющиеся элементы - добавить их содержимое в Set
(который не допускает дубликатов), а затем добавить Set
обратно в ArrayList
:
Set<String> set = new HashSet<>(yourList);
yourList.clear();
yourList.addAll(set);
Разумеется, это разрушает порядок элементов в ArrayList
.
Хотя преобразование ArrayList
в HashSet
эффективно удаляет дубликаты, если необходимо сохранить порядок вставки, я бы посоветовал использовать такой вариант
// list is some List of Strings
Set<String> s = new LinkedHashSet<>(list);
Затем, если нужно получить обратно ссылку на List
, можно снова использовать конструктор преобразования.
На Java 8:
List<String> deduped = list.stream().distinct().collect(Collectors.toList());
Обратите внимание, что контракт hashCode-equals для членов списка должен соблюдаться для правильной работы фильтрации.
Предположим, у нас есть список String
like:
List<String> strList = new ArrayList<>(5);
// insert up to five items to list.
Затем мы можем удалить дубликаты элементов несколькими способами.
List<String> deDupStringList = new ArrayList<>(new HashSet<>(strList));
LinkedHashSet
вместо HashSet
Используя ГуавуList<String> deDupStringList2 = Lists.newArrayList(Sets.newHashSet(strList));
List<String> deDupStringList3 = strList.stream().distinct().collect(Collectors.toList());
Примечание: Если мы хотим собрать результат в конкретной реализации списка , например,. LinkedList
тогда мы можем изменить приведенный выше пример как:
List<String> deDupStringList3 = strList.stream().distinct()
.collect(Collectors.toCollection(LinkedList::new));
Мы можем использовать parallelStream
также в приведенном выше коде, но он может не дать ожидаемых преимуществ производительности. Проверьте этот вопрос для получения дополнительной информации.
Если вам не нужны дубликаты, используйте вместо List
Set. Для преобразования List
в Set
можно использовать следующий код:
// list is some List of Strings
Set<String> s = new HashSet<String>(list);
При необходимости можно использовать ту же конструкцию для обратного преобразования Set
в List
.
Вы также можете сделать это таким образом и сохранить порядок:
// delete duplicates (if any) from 'myArrayList'
myArrayList = new ArrayList<String>(new LinkedHashSet<String>(myArrayList));
Вот способ, который не влияет на порядок вашего списка:
ArrayList l1 = new ArrayList();
ArrayList l2 = new ArrayList();
Iterator iterator = l1.iterator();
while (iterator.hasNext()) {
YourClass o = (YourClass) iterator.next();
if(!l2.contains(o)) l2.add(o);
}
l1 - это оригинальный список, а l2 - список без повторных элементов (Убедитесь, что у YourClass есть метод равных в соответствии с тем, что вы хотите отстаивать равенство)
Потоки Java 8 предоставляют очень простой способ удаления дублирующих элементов из списка. Используя отдельный метод. Если у нас есть список городов, и мы хотим удалить дубликаты из этого списка, это можно сделать в одной строке -
List<String> cityList = new ArrayList<>();
cityList.add("Delhi");
cityList.add("Mumbai");
cityList.add("Bangalore");
cityList.add("Chennai");
cityList.add("Kolkata");
cityList.add("Mumbai");
cityList = cityList.stream().distinct().collect(Collectors.toList());
Существует также ImmutableSet
из Guava в качестве опции (здесь является документация):
ImmutableSet.copyOf(list);
Можно удалить дубликаты из списка массивов, не используя HashSet или еще один список массивов .
Попробуйте этот код..
ArrayList<String> lst = new ArrayList<String>();
lst.add("ABC");
lst.add("ABC");
lst.add("ABCD");
lst.add("ABCD");
lst.add("ABCE");
System.out.println("Duplicates List "+lst);
Object[] st = lst.toArray();
for (Object s : st) {
if (lst.indexOf(s) != lst.lastIndexOf(s)) {
lst.remove(lst.lastIndexOf(s));
}
}
System.out.println("Distinct List "+lst);
Выход есть
Duplicates List [ABC, ABC, ABCD, ABCD, ABCE]
Distinct List [ABC, ABCD, ABCE]
это может решить проблему:
private List<SomeClass> clearListFromDuplicateFirstName(List<SomeClass> list1) {
Map<String, SomeClass> cleanMap = new LinkedHashMap<String, SomeClass>();
for (int i = 0; i < list1.size(); i++) {
cleanMap.put(list1.get(i).getFirstName(), list1.get(i));
}
List<SomeClass> list = new ArrayList<SomeClass>(cleanMap.values());
return list;
}
Вероятно, немного излишне, но мне нравится такая изолированная проблема. :)
Этот код использует временный набор (для проверки уникальности), но удаляет элементы непосредственно в исходном списке. Поскольку удаление элементов внутри ArrayList может вызвать огромное количество копирования массива, метод remove (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
}
}
РЕДАКТИРОВАТЬ: Я думаю, что генерики-материалы здесь не очень ценны.. Ну что ж. :)
public static void main(String[] args){
ArrayList<Object> al = new ArrayList<Object>();
al.add("abc");
al.add('a');
al.add('b');
al.add('a');
al.add("abc");
al.add(10.3);
al.add('c');
al.add(10);
al.add("abc");
al.add(10);
System.out.println("Before Duplicate Remove:"+al);
for(int i=0;i<al.size();i++){
for(int j=i+1;j<al.size();j++){
if(al.get(i).equals(al.get(j))){
al.remove(j);
j--;
}
}
}
System.out.println("After Removing duplicate:"+al);
}
Если вы готовы использовать стороннюю библиотеку, вы можете использовать метод distinct ()
в Eclipse Collections (ранее GS Collections).
ListIterable<Integer> integers = FastList.newListWith(1, 3, 1, 2, 2, 1);
Assert.assertEquals(
FastList.newListWith(1, 3, 2),
integers.distinct());
Преимущество использования distinct ()
вместо преобразования в набор, а затем обратно в список состоит в том, что distinct ()
сохраняет порядок исходного списка, сохраняя первое вхождение каждого элемента. Он реализован с использованием как набора, так и списка.
MutableSet<T> seenSoFar = UnifiedSet.newSet();
int size = list.size();
for (int i = 0; i < size; i++)
{
T item = list.get(i);
if (seenSoFar.add(item))
{
targetCollection.add(item);
}
}
return targetCollection;
Если вы не можете преобразовать свой оригинальный список в тип Eclipse Collections, вы можете использовать ListAdapter, чтобы получить тот же API
MutableList<Integer> distinct = ListAdapter.adapt(integers).distinct();
Примечание: Я коммиттер для Eclipse Collections.
Эти три строки кода могут удалить дублированный элемент из ArrayList или любой коллекции.
List<Entity> entities = repository.findByUserId(userId);
Set<Entity> s = new LinkedHashSet<Entity>(entities);
entities.clear();
entities.addAll(s);
Код:
List<String> duplicatList = new ArrayList<String>();
duplicatList = Arrays.asList("AA","BB","CC","DD","DD","EE","AA","FF");
//above AA and DD are duplicate
Set<String> uniqueList = new HashSet<String>(duplicatList);
duplicatList = new ArrayList<String>(uniqueList); //let GC will doing free memory
System.out.println("Removed Duplicate : "+duplicatList);
Примечание: Определенно, над головой будет память.
Когда вы заполняете ArrayList, используйте условие для каждого элемента. Например:
ArrayList< Integer > al = new ArrayList< Integer >();
// fill 1
for ( int i = 0; i <= 5; i++ )
if ( !al.contains( i ) )
al.add( i );
// fill 2
for (int i = 0; i <= 10; i++ )
if ( !al.contains( i ) )
al.add( i );
for( Integer i: al )
{
System.out.print( i + " ");
}
Мы получим массив {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
Если вы хотите сохранить свой заказ, лучше всего использовать LinkedHashSet . Потому что, если вы хотите передать этот список вставьте запрос, изменяя его, заказ будет сохранен.
Попробуй это
LinkedHashSet link=new LinkedHashSet();
List listOfValues=new ArrayList();
listOfValues.add(link);
Это преобразование будет очень полезно, если вы хотите вернуть список, но не набор.
ArrayList<String> city=new ArrayList<String>();
city.add("rajkot");
city.add("gondal");
city.add("rajkot");
city.add("gova");
city.add("baroda");
city.add("morbi");
city.add("gova");
HashSet<String> hashSet = new HashSet<String>();
hashSet.addAll(city);
city.clear();
city.addAll(hashSet);
Toast.makeText(getActivity(),"" + city.toString(),Toast.LENGTH_SHORT).show();
Вот мой код без использования какой-либо другой структуры данных, такой как set или hashmap
for (int i = 0; i < Models.size(); i++){
for (int j = i + 1; j < Models.size(); j++) {
if (Models.get(i).getName().equals(Models.get(j).getName())) {
Models.remove(j);
j--;
}
}
}