Как удалить дубликаты из ArrayList типа Object?

Я хочу удалить дубликаты из ArrayList типа Alerts, где Alerts — это класс.

Оповещения класса –

public class Alerts implements Parcelable {
    String date = null;
    String alertType = null;
    String discription = null;

    public Alerts() {

    }

    public Alerts(String date, String alertType, String discription) {
        super();
        this.date = date;
        this.alertType = alertType;
        this.discription = discription;
    }
}

Вот как я добавил элементы -

ArrayList<Alerts> alert = new ArrayList<Alerts>();
Alerts obAlerts = new Alerts();

obAlerts = new Alerts();
obAlerts.date = Date1.toString();
obAlerts.alertType = "Alert Type 1";
obAlerts.discription = "Some Text";
alert.add(obAlerts);

obAlerts = new Alerts();
obAlerts.date = Date2.toString();
obAlerts.alertType = "Alert Type 1";
obAlerts.discription = "Some Text";
alert.add(obAlerts);

Что я хочу удалить из них-

Я хочу, чтобы все оповещения имели уникальные obAlerts.date и obAlerts.alertType. Другими словами, удалите повторяющиеся предупреждения obAlerts.date и obAlerts.alertType.

Я попробовал это -

Alerts temp1, temp2;
String macTemp1, macTemp2, macDate1, macDate2;

for(int i=0;i<alert.size();i++)
 {    
    temp1 = alert.get(i);  
    macTemp1=temp1.alertType.trim(); 
    macDate1 = temp1.date.trim();

    for(int j=i+1;j<alert.size();j++)
    {

         temp2 = alert.get(j);  
        macTemp2=temp2.alertType.trim();  
        macDate2 = temp2.date.trim();

        if (macTemp2.equals(macTemp1) && macDate1.equals(macDate2))  
        {   
           alert.remove(temp2);           
        } 

    }
 }

Я тоже пробовал-

HashSet<Alerts> hs = new HashSet<Alerts>();
hs.addAll(obAlerts);
obAlerts.clear();
obAlerts.addAll(hs);

person My God    schedule 18.06.2014    source источник
comment
Вы хотите, чтобы каждый объект имел разные date И разные alertType. Таким образом, вы должны удалить объект, если date ИЛИ alertType одинаково для двух объектов.   -  person G.T.    schedule 18.06.2014
comment
@Г.Т. ДА. Как удалить такие дубликаты?   -  person My God    schedule 18.06.2014
comment
Как и вы. Просто замените && на || в последнем if.   -  person G.T.    schedule 18.06.2014


Ответы (4)


Сначала сохраните свои данные в массиве, а затем разделите их по одной строке, пока длина этих данных не выполнится arry и не сравнится с реальными данными по условию if и повторите их,

HashSet<String> hs = new HashSet<String>(); 

for(int i=0;i<alert.size();i++)
{
    hs.add(alert.get(i).date + ","+ alert.get(i).alertType;
}

alert.clear();

String alertAll[] = null;
for (String s : hs) {   

    alertAll = s.split(",");
    obAlerts = new Alerts();
    obAlerts.date = alertAll[0];
    obAlerts.alertType = alertAll[1];
    alert.add(obAlerts);
}
person Samaskhan    schedule 18.06.2014
comment
Можете ли вы привести пример для иллюстрации? - person My God; 18.06.2014
comment
@VedPrakash Не делайте этого самостоятельно, если только вы не изучаете структуры данных. - person Marius; 18.06.2014
comment
Спасибо, вы были правы! - person My God; 18.06.2014

Вам нужно указать, как класс определяет равенство, переопределяя пару методов:

public class Alert {

    String date;
    String alertType;

    @Override
    public boolean equals(Object o) {
        if (this == 0) {
            return true;
        }
        if ((o == null) || (!(o instanceof Alert)))
            return false;
        }
        Alert alert = (Alert) o;
        return this.date.equals(alert.date)
                && this.alertType.equals(alert.alertType);
    }

    @Override
    public int hashCode() {
        int dateHash;
        int typeHash;
        if (date == null) {
            dateHash = super.hashCode();
        } else {
            dateHash = this.date.hashCode();
        }
        if (alertType == null) {
            typeHash = super.hashCode();
        } else {
            typeHash = this.alertType.hashCode();
        }
        return dateHash + typeHash;
    }
}

Затем вы можете просмотреть свой ArrayList и добавить элементы, если их еще нет, поскольку Collections.contains() использует эти методы.

public List<Alert> getUniqueList(List<Alert> alertList) {
    List<Alert> uniqueAlerts = new ArrayList<Alert>();
    for (Alert alert : alertList) {
        if (!uniqueAlerts.contains(alert)) {
            uniqueAlerts.add(alert);
        }
    }
    return uniqueAlerts;
}

Однако, сказав все это, вы можете захотеть пересмотреть свой дизайн, чтобы использовать набор или один из его семейств, который не допускает дублирования элементов. Зависит от вашего проекта. Вот сравнение типов коллекций

person indivisible    schedule 18.06.2014
comment
Я хочу равенства date и alertType. Итак, могу ли я использовать return this.date.equals(alert.date) && this.alertType.equals(alert.alertType); в методе equals? - person My God; 18.06.2014
comment
Вы можете использовать любые условия, которые вам нравятся, но убедитесь, что вы включили поле alertType в расчет hashCode; два метода должны совпадать, так что если a.equals(b), то a.hashCode() equals b.hashCode() - person indivisible; 18.06.2014
comment
Вместо зацикливания Statemts для уникального списка просто используйте List‹Alerts› depdupeCustomers = new ArrayList‹Alerts›( new LinkedHashSet‹Alerts›(alert)); - person kalyan pvs; 18.06.2014
comment
Код данного примера можно улучшить. Никогда не делайте бросок вслепую и полагайтесь на попытку-поймать. Использование исключений для потока управления — это антишаблон, потому что создавать исключения очень и очень дорого. Кроме того, этот метод equals не соответствует спецификации javadoc (сравните поток, связанный с моим ответом), поскольку он выдаст NullPointerException, когда вы передадите ему null. - person hiergiltdiestfu; 18.06.2014
comment
@indivisible Что должно возвращаться в методе hashcode(), если alertType также рассматривается вместе с date? Будет ли это работать - int a = this.date.hashCode() + this.alertType.hashCode();return a; - person My God; 18.06.2014
comment
@hiergiltdiestfu, внесены изменения, которые решают ваши проблемы. - person indivisible; 18.06.2014
comment
@indivisible - Нет, моя проблема состоит в том, чтобы добавить alertType и date для проверки на равенство. Поэтому, пожалуйста, добавьте еще alertType. - person My God; 18.06.2014
comment
@VedPrakash, решать тебе. hashCode() возвращает int, поэтому любой последовательный расчет, который вы выполняете с хэш-кодами обоих полей, должен работать хорошо. - person indivisible; 18.06.2014
comment
@VedPrakash, еще одно редактирование; последний. Вы должны быть в состоянии выяснить остальное самостоятельно - person indivisible; 18.06.2014
comment
Возможно, сейчас я говорю своим голосом рецензента кода, но последняя версия вашего метода hashCode непоследовательна в том смысле, что она будет давать разные результаты всякий раз, когда хотя бы одно из полей первичного ключа равно null. Например. два экземпляра, где дата null и тип оповещения одинаковы в обоих экземплярах. Ваша реализация будет предоставлять различные хэш-значения для этих семантически идентичных экземпляров, потому что вы откатываетесь к super.hashCode() в случае null. Однако давайте оставим выбор правильного резервного значения в качестве упражнения для OP, не так ли? :) - person hiergiltdiestfu; 18.06.2014
comment
Да, я думаю, я мог бы добавить произвольное число к одному из них, но, как вы поняли, его код для работы не мой. Кроме того, я только что обнаружил мастер создания автоматического равенства/хэш-кода моей IDE благодаря вашей ссылке выше. Спасибо за это. - person indivisible; 18.06.2014

Вы можете использовать Set<>. По своей природе наборы не содержат дубликатов. Вам просто нужно убедиться, что у вас есть правильные методы hashCode() и equals().

person lordgasmic    schedule 18.06.2014
comment
Смотрите обновление. Я использовал HashSet, но дубликаты все еще там. Вы можете проиллюстрировать? - person My God; 18.06.2014

В своем классе Alerts переопределите методы hashCode и equals, чтобы они зависели от значений полей, которые вы хотите использовать в качестве первичных ключей. После этого вы можете использовать HashSet для хранения уже просмотренных экземпляров при повторении ArrayList. Когда вы найдете экземпляр, которого нет в HashSet, добавьте его в HashSet, в противном случае удалите его из ArrayList. Чтобы облегчить себе жизнь, вы можете вообще перейти на HashSet и покончить с дубликатами как таковыми.

Помните, что для переопределения hashCode и equals применяются некоторые ограничения.

В этом потоке есть несколько полезных указателей о том, как писать хорошие hashCode функции. Важный урок заключается в том, что простого сложения хэш-кодов всех зависимых полей недостаточно, потому что тогда замена значений между полями приведет к идентичным хэш-кодам, что может быть нежелательно (сравните замену местами имени и фамилии). Вместо этого перед добавлением следующего атомарного хэша обычно выполняется какая-то операция сдвига, например. умножение на простое число.

person hiergiltdiestfu    schedule 18.06.2014
comment
Смотрите обновление. Я пробовал HashSet безуспешно. Вы можете проиллюстрировать? - person My God; 18.06.2014
comment
@VedPrakash Переопределение hashCode и equals в вашем классе Alerts обязательно. Без надлежащей операции с хэш-кодом в ключевом объекте HashSet бесполезен, поскольку он будет основывать решение, является ли он дубликатом? на собственном хеш-коде, который отличается для всех отдельных объектов независимо от значения полей. - person hiergiltdiestfu; 18.06.2014
comment
@VedPrakash Обновлен мой ответ, чтобы добавить информацию о том, как писать хорошие функции hashCode. - person hiergiltdiestfu; 18.06.2014